C++11 学习笔记-05.rvalue references

引用声明

声明具名变量为引用,即既存对象或函数的别名。

左值和右值的概念

左值是可以放在赋值号左边可以被赋值的值;左值必须要在内存中有实体;
右值当在赋值号右边取出值赋给其他变量的值;右值可以在内存也可以在CPU寄存器。
一个对象被用作右值时,使用的是它的内容(值),被当作左值时,使用的是它的地址。

语法

声明具名变量为引用,即既存对象或函数的别名。


& attr(可选) 声明符 (1)
&& attr(可选) 声明符 (2) (C++11 起)

  • 左值引用声明符:声明 S& D; 将 D 声明为到 声明说明符序列 所确定的类型 S 的左值引用。
  • 右值引用声明符:声明
    S&& D; 将 D 声明为到 声明说明符序列 所确定的类型 S 的右值引用。

右值引用

值引用可用于为临时对象延长生存期(注意,左值引用亦能延长临时对象生存期,但不能通过左值引用修改它们):

#include 
#include 
 
int main()
{
    std::string s1 = "Test";
//  std::string&& r1 = s1;           // 错误:不能绑定到左值
 
    const std::string& r2 = s1 + s1; // okay:到 const 的左值引用延长生存期
//  r2 += "Test";                    // 错误:不能通过到 const 的引用修改
 
    std::string&& r3 = s1 + s1;      // okay:右值引用延长生存期
    r3 += "Test";                    // okay:能通过到非 const 的引用修改
    std::cout << r3 << '\n';
}

悬垂引用

尽管引用一旦初始化,就始终指代一个有效的对象或函数,但有可能创建一个程序,被指代对象的生存期结束,但引用仍保持可访问(悬垂(dangling))。访问这种引用是未定义行为。 一个常见例子是返回自动变量的引用的函数:

std::string& f()
{
    std::string s = "Example";
    return s; // 退出 s 的作用域:
              // 调用其析构函数并解分配其存储
}
 
std::string& r = f(); // 悬垂引用
std::cout << r;       // 未定义行为:从悬垂引用读取
std::string s = f();  // 未定义行为:从悬垂引用复制初始化

注意,右值引用和到 const 的左值引用能延长临时对象的生存期.这是一种危险的做法。

若被指代对象被销毁(例如通过显式的析构函数调用),但存储尚未被解分配,则到生存期外的对象的引用仍能以有限的方式使用,且当在同一存储中重新创建对象时也可以变为有效(细节见在生存期之外进行访问)。

你可能感兴趣的:(C++11)