右值和左值,右值引用和左值引用

右值和左值

左值右值的形式区分(或者称语法区分)是能否用取地址&运算符;语义区分(即其本质涵义)在于表达式代表的是持久对象还是临时对象。

当一个对象被用作右值的时候,用的是对象的值(内容),当对象被用作左值的时候,用的是对象的身份(在内存中的位置) ——CppPrimer, 5th

返回左值的有:

  • 赋值运算符需要一个(非常量)左值作为其左侧运算对象,得到的结果也是一个左值
  • 取地址作用于一个左值运算对象,返回一个指向该运算对象的指针, 该指针是一个右值
  • 内置的解引用运算符,下标运算符,迭代器解引用,string 和 vector 的下标运算符,他们的求值结果都是左值
  • 内置类型和迭代器的递增递减运算符作用于左值,而前置版本多的结果是左值

右值引用和左值引用


为了支持移动操作,新标准引入右值引用(&&)。右值引用必须绑定到右值,其有一个重要的性质——只能绑定到一个将要销毁的对象。使用右值引用绑定到一个对象后,可以给该对象赋予新值或者销毁,但不能再使用它。

int i = 42;            
int &r = i;               //正确:r引用i
int &&rr = i;             //错误:不能将一个右值绑定到一个左值上
const int &r3 = i * 42    //正确:我们可以将一个const引用绑定到一个左值
int &&rr2 = i * 42        // 正确:将rr2绑定到乘法结果上

注意 一个变量表达式是左值

int &&rr1 = 42;
int &&rr2 = rr1;    //错误,rr1是一个右值引用类型的变量,而变量表达式都是左值

右值特例

在一个对象上调用成员函数, 而不管该对象是否是一个左值还是右值

string s1 = "a value", s2 = "another";
auto n = (s1 + s2).find('a');

甚至 s1 + s2 = "wow!";

在新标准中 通过在参数列表后放置一个引用限定符来限制函数用于左值还是右值

class Foo
{
public:
    Foo &operator=(const Foo&) &;        //只能向可修改的左值赋值
};

Foo &Foo::operator=(const Foo &rhs) &
{
    return *this;
}

你可能感兴趣的:(C++零散笔记)