引用限定符

通常,我们在一个对象上调用成员函数,而不管该对象是一个左值还是一个右值。例如∶

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

此例中,我们在一个string右值上调用find成员,该string右值是通过连接两个 string 而得到的。有时,右值的使用方式可能令人惊讶∶

s1 + s2 = "wow!";

此处我们对两个 string 的连接结果——一个右值,进行了赋值。

在旧标准中,我们没有办法阻止这种使用方式。为了维持向后兼容性,新标准库类仍然允许向右值赋值。但是,我们可能希望在自己的类中阻止这种用法。

在此情况下,我们希望强制左侧运算对象(即,this 指向的对象)是一个左值。

我们指出this的左值/右值属性的方式与定义const成员函数相同,即,在参数列表后放置一个引用限定符(reference qualifier)∶

class Foo {
public:
    Foo& operator=(const Foo &) &;
    // Foo的其他函数
};

Foo& Foo::operator=(const Foo &rhs) & {
    // 执行rhs赋予本对象所需的操作
    return *this;
}

引用限定符可以是&或&&,分别指出this可以指向一个左值或右值。

类似const 限定符,引用限定符只能用于(非static)成员函数,且必须同时出现在函数的声明和定义中。对于&限定的函数,我们只能将它用于左值;

对于&s限定的函数,只能用于右值∶

Foo &retFoo ();       // 返回一个引用; retFoo调用是一个左值
Foo retVal ();         // 返回一个值; retVal 调用是一个右值
Foo i,j;               // i和j是左值 
i = j;                 // 正确∶ i是左值
retFoo()= j;           // 正确∶ retFoo()返回一个左值
retVal()= j;           // 错误∶ retVal()返回一个右值 
i = retVal();          // 正确∶ 我们可以将一个右值作为赋值操作的右侧运算对象

一个函数可以同时用 const和引用限定。在此情况下,引用限定符必须跟随在 const限定符之后∶

class Foo { 
public:
    Foo someMem () & const;      // 错误∶ const 限定符必须在前  
    Foo anotherMem() const &;    // 正确∶ const 限定符在前
);
posted @ 2021-02-27 18:51  DearLeslie  阅读(343)  评论(0编辑  收藏  举报