引用(取别名)
语法
数据类型 &别名 = 原名
引用的本质
引用是一个常量指针
int &a = b;
等价于 int *const c = &b;
cout<<a;
/等价于cout<<*c;
int b = 1;
int &a = b;//等价于 int *const c = &b;(也是在编译器眼里)
cout<<a;//等价于cout<<*c;
printf("%d\n", &a);
printf("%d\n", &b);//结果是一致的 等价于&*c
因为引用就是共同管理一片内存
并且此时a是需要在栈中占用额外空间的
struct Test
{
int a[5];//占用20
int &b;//说明这里和指针一样占用了4个字节
//这样看起来违反了引用必须初始化的原则 但是实际上应该是引用分配内存空间时,必须进行初始化! 如果此时创建这个结构体对象就会报错
}
int main()
{
cout<<"结构体占用的内存空间字节大小为:"<<sizeof(Test);//24
}
引用注意事项
1.引用必须要初始化
int &b;//这是错误的
很容易理解 int* const a常量指针必须初始化
引用作为函数的返回值
不要返回局部变量的引用
int &tes()
{
int a = 10;
return a;//这样就会返回a的别名出去;
}
int &b = tes();//这样就出错了 因为a的地址被释放了 int *constc = &a此时a的地址已经被释放 无法获取地址
函数的调用可以作为左值
也就是上面那段代码 如果变成 static int a = 10;就是可以的
int &tes()
{
static int a = 10;
return a;//这样就会返回a的别名出去;
}
int &b = tes();
cout<<b;
tes() = 20;
cout<<b;
结果是10 20
右值引用
用 “&&” 表示右值引用
int &a = 1; //本来这样是错误的 因为1是右值 不能对右值进行引用
/*但是在C++11中是可以的*/
int num = 10;
//int && a = num; //右值引用不能初始化为左值
int && a = 10;//也必须直接初始化
cout<<a<<endl;//10
a = 11;
cout<<a<<endl;//11
常量引用
const int&b = 10; 编译器会自动改成 int temp = 10; int&b = temp
ref和cref
std::ref 用于包装按引用传递的值。
std::cref 用于包装按const引用传递的值。