这里的 const 修饰符不是不必要的吗?
Effective C++"第 3 条说尽可能使用 const",并给出了如下示例:
The "Effective C++" Item 3 says "Use const whenever possible", and it gives an example like:
const Rational operator*(const Rational& lhs,
const Rational& rhs);
为了防止客户犯下这样的暴行:
to prevent clients from being able to commit atrocities like this:
Rational a, b, c;
...
(a * b) = c; // invoke operator= on the result of a*b!
但是函数的非引用返回值不是已经是右值了吗?那么为什么要这么做呢?
But isn't the non-reference return value of functions allready a rvalue? So why bother doing this?
推荐答案
重点是对于类类型(但不是内置类型),a = b
是只是 a.operator=(b)
的简写,其中 operator= 是一个成员函数.并且可以在 Rational::operator*
创建的 (a * b)
等右值上调用成员函数.为了强制执行与内置右值类似的语义(do as the ints do"),一些作者(包括 Meyers)在 C++98 中建议使用 const-rvalue 为具有此类运算符的类返回.
The point is that for class types (but not for builtin types), a = b
is just a shorthand to a.operator=(b)
, where operator= is a member function. And member functions can be called on rvalues such (a * b)
created by Rational::operator*
. To enforce similar semantics as for builtin rvalues ("do as the ints do") some authors (Meyers including) recommended in C++98 to return by const-rvalue for classes with such operators.
但是,在 C++11 中,通过 const-rvalue 返回是一个坏主意,因为它会抑制移动语义,因为 const rvalues 不能绑定到 T&&
.
However, in C++11 returning by const-rvalue is a bad idea as it will inhibit move semantics because const rvalues cannot bind to T&&
.
在他的笔记中 新 C++ (C++11) 概述,Scott Meyers 给出了与他的旧书中完全相同的示例,并得出结论,现在添加 const 返回值被认为是糟糕的设计.现在推荐的签名是
In his notes An overview of the new C++ (C++11), Scott Meyers gives precisely the same example from his old book, and concludes that it is now considered poor design to add the const return value. The recommended signature is now
Rational operator*(const Rational& lhs, const Rational& rhs);
更新:正如@JohannesSchaub-litb 在评论中暗示的那样,在 C++11 中,您还可以使用 赋值运算符上的引用限定符,使其只接受左值作为其左参数(即 *this
指针,这就是为什么此功能也称为右值引用"的原因为了这").您需要 g++ >= 4.8.1(刚刚发布)或 Clang >= 2.9 才能使用它.
UPDATE: As implied by @JohannesSchaub-litb in the comments, in C++11 you can also use a reference qualifier on the assignment operator so that it will only accept lvalues as its left argument (i.e. the *this
pointer, which is why this feature is also known as "rvalue references for *this"). You'll need g++ >= 4.8.1 (just released) or Clang >= 2.9 to make use of it.
相关文章