C++ 基础 引用
1.引用的本质
int b = 10;
int &a = b;
等效于:
int * const a = &b;
由于 a 是 const声明,所以一旦定义无法修改,所以要在定义时就要赋初值。
实际使用时:
a = 10; ==> *b = 10;
2. 引用于函数结合
(1)引用做函数参数
int func(int &a)
{
...
}
使用时:
int b = 10;
func(b);
为了分析语法,将其转换为指针,编译器在实参给形参赋值时:
int &a = b; ===> int *const a = &b;
实际使用:
a = 10; ===> *b = 10;
所以实现了间接赋值。
(2)引用做函数返回值
int &func() { int ret = 10; return ret; }
int main()
{
int a = func(); // gcc 中,这里出现段错误
int &b = func();
cout << a << endl;
cout << b << endl; // gcc 中,这里段错误
}
在 vs 中,debug版本和 release版本的输出不同。
所以上面的代码是错误的。
分析原因:
int a = func(); ==>
int &tmp = ret; === > int *const tmp = &ret;
a = tmp; ===> a = *(&ret);
其中 tmp 是 隐藏变量,一般在寄存器中。
由于 函数返回后,局部变量 ret 空间释放,所以对无效空间的访问是未知的。
int &b = func(); ==>
int &tmp = ret; ===> int *const tmp = &ret;
int &b = tmp; ===> int *const b = tmp; ==> int *const b = &ret;
可以看出这里不存在非法地址访问,所以这句不会报错。
cout << b << endl; ===> cout << *(&ret) << endl;
这里是非法地址访问。报错
由于上面的非法地址访问的本质原因是栈空间的释放,所以如果变量的存储类在堆或数据段就不会有错。
3. 引用与指针
(1)引用指针
int &b = c;
int & * a = &b;
上面的表达式是错误的,因为 指针不能指向引用,原因是 c++之父 不希望 引用和指针一样出现多级引用,同理也没有 引用的引用。
(2)指针引用
int *b = &c;
int * & a = b;
这是成立的,相当于:
int * * const a = &b;
4. 引用与 const
(1)使用变量初始化常引用
int a = 10;
const int &b = a;
a = 11;
b = 12; // 错误
通过常引用赋予变量只读属性。
(2)使用字面量初始化常引用
int &a = 10; // 错误,因为字面量没有地址,无法引用
const int &b = 10;
常引用可以引用字面量,当常引用引用字面量时,c++编译器为字面量分配空间,并让常引用符号作为该空间的别名。
上一篇: ORACLE公司传奇历史