C++ 引用
引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。
C++ 引用 vs 指针
引用很容易与指针混淆,它们之间有三个主要的不同:
- 不存在空引用。引用必须连接到一块合法的内存。
- 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
- 引用必须在创建时被初始化。指针可以在任何时间被初始化
-
C++ 把引用作为返回值
-
当返回一个引用时,要注意被引用的对象不能超出作用域。所以返回一个对局部变量的引用是不合法的,但是,可以返回一个对静态变量的引用。
int& func(){ int q;//! return q; //在编译时发生错误static int x;return x; // 安全,x 在函数作用域外依然是有效的}(1)以引用返回函数值,定义函数时需要在函数名前加 &
(2)用引用返回一个函数值的最大好处是,在内存中不产生被返回值的副本。
引用作为返回值,必须遵守以下规则:
- (1)不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。
- (2)不能返回函数内部new分配的内存的引用。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一 个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。
- (3)可以返回类成员的引用,但最好是const。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常 量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。
(一)引用更接近const指针,必须在创建时进行初始化,一旦引用和某个变量关联起来,该引用就会一直指向该变量。
int rats = 10; int &rodents = rats;
上面代码实际上是下述代码的伪装表示:
int rats = 10; int * const pr = &rats;
例子:
#include <iostream> using namespace std; int main() { int rats = 100; int &rodent = rats; cout << "rats = "<<rats<<", rosent = "<<rodent<<endl; cout << "rats address = "<<&rats<<endl; cout << "rosent address = "<<&rodent<<endl; cout <<"==================================="<<endl; int bunnies = 50; rodent = bunnies; cout << "rats = "<<rats<<", rosent = "<<rodent<<", bunnies = "<<bunnies<<endl; cout << "rats address = "<<&rats<<endl; cout << "rosent address = "<<&rodent<<endl; cout << "bunniess address = "<<&bunnies<<endl; return 0; }
输出结果:
rats = 100, rosent = 100 rats address = 0xbfce21e4 rosent address = 0xbfce21e4 =================================== rats = 50, rosent = 50, bunnies = 50 rats address = 0xbfce21e4 rosent address = 0xbfce21e4 bunniess address = 0xbfce21e8
从结果可以看出,虽然在调用 rodent = bunnies; 后引用 rosent 的值变为 50,但是 rosent 所指向的地址空间还是指向了 rats,
没有发生改变,说明 rodent = bunnies; 只是将 bunnies 的值赋值给引用 rodent 所指向的变量,没有改变引用的指向。
(二)int& r = i; 和 int r = i; 不同之处应该是内存的分配吧,后者会再开辟一个内存空间
#include <iostream> using namespace std; int main () { int i; int& r = i; i = 5; cout << "Value of i : " << i << endl; cout << "Value of i reference : " << r << endl; cout << "Addr of i: " << &i << endl; cout << "Addr of r: " << &r << endl; int x; int y = x; x = 6; cout << "Value of x : " << x << endl; cout << "Value of y : " << y << endl; cout << "Addr of x: " << &x << endl; cout << "Addr of y: " << &y << endl; return 0; }
输出结果:
Value of i : 5 Value of i reference : 5 Addr of i: 0x7ffffc9517b4 Addr of r: 0x7ffffc9517b4 Value of x : 6 Value of y : 4197104 Addr of x: 0x7ffffc9517b0 Addr of y: 0x7ffffc9517ac