首页 > 代码库 > C++ 引用

C++ 引用

C++11 之后,C++的引用扩充为 非常量左值引用,常量左值引用,非常量右值引用,常量右值引用。

什么是左值?什么是右值?左值、右值都是针对表达式而言的,左值是指表达式结束后依然存在的持久对象,右值是指表达式结束时就不存在的临时对象。一个区分左值、右值的便捷方法是:看能不能对表达式取地址,如果能,则为左值,否则为右值。

什么是引用?引用并非对象,相反的,它只是为一个已经存在的对象所起的另外一个名字。定义了一个引用之后,对其进行的所有操作都是在与之绑定的对象上进行的。

引用又分为常量引用、非常量引用,它们的区别是:通过非常量引用可以对与之绑定的对象做所有操作,而对通过常量引用,则不可以对与之绑定的对象做任何修改操作。

引用在定义时需要同时初始化,即完成与一个对象的绑定。以上四类引用对可以与之绑定的对象是有要求的。

非常量左值引用(T & = x) :  x只能是一个T类型的非常量左值。

常量左值引用 (const T & = x) : x可以是左值,也可以是右值。x的类型可以是T类型以及所有可以隐式转换为T类型的其它类型。x既可以是常量也可是非常量。

非常量右值引用(T && = x) : 如果X是T类型的,则必须是非常量右值。如果X是可以隐式转换为T类型的其它类型,则左值、右值都可以。

常量右值引用(const T && = x) :可以指向T类型的常量、非常量右值。如果X是可以隐式转换为T类型的其它类型,则左值、右值都可以。

当引用绑定的对象被销毁后,这个引用就失效了,使用失效的引用是未定义的行为,一般就是程序崩溃。所以引用绑定的对象啥时候被销毁是需要关注的。引用绑定左值没啥问题,但指向右值,不是说右值在表达式结束后就销毁了吗?那定义的这个引用还有啥用?引发未定义的行为?引用定义有两个场景:函数参数传递、其它。

先说函数参数传递。比如函数声明为 void fun(const string & param),调用时使用右值初始化param: fun( string()); 。可以看到,string()虽然是个右值,fun(string())这个表达式结束后被销毁了,但这时fun函数已经运行完了,所以在fun运行期间,引用param一直有效。所以,这个场景引用绑定右值完全没有问题。

再说其它(函数作用域、全局作用域、类作用域内定义引用),以函数作用域为例:

class test1{public:    test1(int ){        cout<<"cc"<<endl;    }    test1(const test1 &)    {        cout<<"copy"<<endl;    }    ~test1(){cout<<"destroy"<<endl;}};void fun(){   const test1 &x = test1(2); 
  test1 y(x);}

  以上代码中,x绑定了一个右值,而这个右值按照常规,在const test1 &x = test1(2); 这个表达式结束后就被销毁了,但实际上却没有。在这种情况下,这个右值的生命期被延长了,test1(2)等同于一个匿名的左值变量,在退出它的作用域时才被销毁。其行为等同于以下代码:

void fun(){    test1 tmp(2);    const test1 &x = tmp;    test1 y(x);}

  以上讨论的右值不包括字面常量,如果右值是字面常量,编译器会为其定义一个临时变量来存储它的值,然后引用绑定的就是这个临时变量。当然,这个临时变量也是个右值,所以其生命期的规律就是普通右值的规律。

  常量左值引用 const T &  = x ,x还可以指向不是T类型的左值、右值,只要x的类型可以隐式转换为T类型。其原理是这样的:编译器将x隐式转换为T类型的一个临时变量,然后 常量左值引用绑定的就是这个临时变量。这个临时变量当然是个右值。右值的生命期的规律上面已经讲过。

class test1{public:    test1(int ){        cout<<"cc"<<endl;    }    test1(const test1 &)    {        cout<<"copy"<<endl;    }    ~test1(){cout<<"destroy"<<endl;}};int main(){    test1 x(3);    //test1 && y = x;   //error,右值引用只能指向右值    int i = 3;    test1 && y = i; //right,y指向的是用i生成的一个临时变量:右值    system("pause");    return 0;}

 

  

 

C++ 引用