Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Isn't the const modifier here unnecessary? [duplicate]

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?

like image 291
Joey.Z Avatar asked May 30 '13 11:05

Joey.Z


2 Answers

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.

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&&.

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); 

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.

like image 103
TemplateRex Avatar answered Oct 14 '22 03:10

TemplateRex


The const modifier on the return value is not necessary and can hinder move semantics. The preferred way of preventing assignment to rvalues in C++11 is to use "ref-qualifiers."

struct Rational {   Rational & operator=( Rational other ) &; // can only be called on lvalues };  Rational operator*( Rational const & lhs, Rational const & rhs );  Rational a, b, c;  (a * b) = c; // error 
like image 32
Andrew Durward Avatar answered Oct 14 '22 01:10

Andrew Durward