引用限定符
通常,我们在一个对象上调用成员函数,而不管该对象是一个左值还是一个右值。例如∶
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 限定符在前
);