引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
**类型& 引用变量名(对象名) = 引用实体;**
void TestRef()
{
int a = 10;
int& ra = a;//<====定义引用类型
printf("%p\n", &a);
printf("%p\n", &ra);
cout << a << endl;
cout << ra << endl;
ra -= 1;
cout << a << endl;
cout << ra << endl;
}
int main()
{
TestRef();
system("pause");
return 0;
}
执行结果:
void TestRef2()
{
int a = 10;
//int& ra; // 该条语句编译时会出错,定义时没有初始化
int& ra = a;
int& rra = a;
printf("%p %p %p\n", &a, &ra, &rra);
}
常引用声明方式:const 类型标识符&引用名=目标变量名;
void TestConstRef()
{
const int a = 10;
//int& ra = a; // 该语句编译时会出错,a为常量
const int& ra = a;
// int& b = 10; // 该语句编译时会出错,b为常量
const int& b = 10;
double d = 12.34;
//int& rd = d; // 该语句编译时会出错,类型不同
const int& rd = d; }
用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为const,达到了引用的安全性。
1、传递可变参数 2.做返回值
void Swap(int& left, int& right) {
int temp = left;
left = right;
right = temp;
}
int& TestRefReturn(int& a) {
a += 10;
return a;
}
int main()
{
int a = 8, b = 9; Swap(a, b);
cout << a << b << endl;
TestRefReturn(a);
cout << a << endl;
return 0;
}
注意:如果函数返回时,离开函数作用域后,其栈上空间已经还给系统,因此不能用栈上的空间作为引用类型 返回。如果以引用类型返回,返回值的生命周期必须不受函数的限制(即比函数生命周期长)。
★ 相同点: 都是地址的概念; 指针指向一块内存,它的内容是所指内存的地址;引用是某块内存的别名。 ★ 区别: 1. 指针是一个实体,而引用仅是个别名; 2. 引用使用时无需解引用(*),指针需要解引用; 3. 引用只能在定义时被初始化一次,之后不可变;指针可变; 4. 引用没有 const,指针有 const; 5. 引用不能为空,指针可以为空; 6. “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小; 7. 指针和引用的自增(++)运算意义不一样; 8.从内存分配上看:程序为指针变量分配内存区域,而引用不需要分配内存区域。
内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展);也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。但在选择使用内联函数时,必须在程序占用空间和程序执行效率之间进行权衡,因为过多的比较复杂的函数进行内联扩展将带来很大的存储资源开支。另外还需要特别注意的是对递归函数的内联扩展可能引起部分编译器的无穷编译。
// F.h
#include <iostream>
using namespace std;
inline void f(int i);
// F.cpp
#include "F.h"
void f(int i) {
cout << i << endl; }
// main.cpp
#include "F.h"
比特科技
int main()
{ f(10);
return 0; }
// 链接错误:main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl f(int)" (?
f@@YAXH@Z),该符号在函数 _main 中被引用
auto是一个C/C++语言存储类型,仅在语句块内部使用,初始化可为任何表达式,其特点是当执行流程进入该语句块的时候初始化可为任何表达式。
#include<iostream>
using namespace std;
int TestAuto()
{
return 10;
}
int main()
{
int a = 10;
auto b = a;
auto c = 'a';
auto d = TestAuto();
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
system("pause");
return 0;
}
运行结果:
【注意】使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。
1. auto与指针和引用结合起来使用 用auto声明指针类型时,用auto和auto*没有区别,但用auto声明引用类型时则必须加& 2. 在同一行定义多个变量 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
#include<iostream>
using namespace std;
void TestAuto()
{
auto a = 1, b = 2;
//auto c = 3, d = 4.0; // 该行代码会编译失败,因为c和d的初始化表达式类型不同
}
int main()
{
int a = 10;
auto b = a;
auto c = 'a';
auto* e = &a;
auto& f = a;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(e).name() << endl;
cout << typeid(f).name() << endl;
system("pause");
return 0;
}
void TestAuto(auto a) {}
void TestAuto()
{
int a[] = {1,2,3};
auto b[] = {4,5,6};
}
for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。 语法形式:
for(declaration:expression)
{
statement
}
其中: expression部分表示一个对象,用于表示一个序列。 declaration部分负责定义一个变量,该变量将被用于访问序列中的基础元素。 每次迭代,declaration部分的变量会被初始化为expression部分的下一个元素值。
(1)和普通循环一样,也可以采用continue跳出循环的本次迭代。 (2)用break来终止整个循环
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (int y : x) {
cout << y << " ";
}
for (auto y : x) {
cout << y << " ";
}
cout << endl;
for (auto &y : x) {
cout << y << " ";
}
cout << endl;
for (const auto &y : x) {
cout << y << " ";
}
cout << endl;
cout << "end of integer array test" << endl;
cout << endl;
vector<double> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i + 0.14159);
}
for (const auto &j : v) {
cout << j << " ";
}
cout << endl;
cout << "end of vector test" << endl;
system("pause");
}
nullptr:是C++空指针类型的关键字,nullptr是在C++11中引入的。 传统意义上来说,c++把NULL、0视为同一种东西,有些编译器将NULL定义为 ((void*)0),有些将其定义为0.
c++不允许直接将void隐式的转化为其他类型,但是如果NULL被定义为 ((void)0), 当编译char p = NULL;NULL只好被定义为0。 还有: void func(int); void func(char); 如果NULL被定义为0,func(NULL)会去调用void func(int),这是不合理的 所以引入nullptr,专门用来区分0、NULL。 nullptr的类型为nullptr_t,能够隐式的转换为任何指针。
nullptr 与 nullptr_t:
typedef decltype(nullptr) nullptr_t;
注意:
总结,刚接触C++,整理的知识不是很有条理,有问题的地饭否还望指出!!