Should I still return const objects in C++11?

c++, c++11, constants, performance

Solution

Returning const objects is a workaround that might cause other problems. Since C++11, there is a better solution for the assignment issue: Reference Qualifiers for member functions. I try to explain it with some code:

int foo(); // function declaration
foo() = 42; // ERROR

The assignment in the second line results in a compile-time error for the builtin type `int` in both C and C++. Same for other builtin types. That's because the assignment operator for builtin types requires a non-const lvalue-reference on the left hand side. To put it in code, the assignment operator might look as follows (invalid code):

int& operator=(int& lhs, const int& rhs);

It was always possible in C++ to restrict parameters to lvalue references. However, that wasn't possible until C++11 for the implicit first parameter of member functions (`*this`).

That changed with C++11: Similar to const qualifiers for member functions, there are now reference qualifiers for member functions. The following code shows the usage on the copy and move operators (note the `&` after the parameter list):

struct Int
{
    Int(const Int& rhs) = default;
    Int(Int&& rhs) noexcept = default;
    ~Int() noexcept = default;
    auto operator=(const Int& rhs) & -> Int& = default;
    auto operator=(Int&& rhs) & noexcept -> Int& = default;
};

With this class declaration, the assignment expression in the following code fragment is invalid, whereas assigning to a local variable works - as it was in the first example.

Int bar();
Int baz();
bar() = baz(); // ERROR: no viable overloaded '='

So there is no need to return const objects. You can restrict the assigment operators to lvalue references, so that everything else still works as expected - in particular move operations.

See also:

- What is "rvalue reference for *this"?

Problem

Possible Duplicate: Should I return const objects? (The original title of that question was: int foo() or const int foo()? explaining why I missed it.) Effective C++, Item 3: Use const whenever possible. In particular, returning const objects is promoted to avoid unintended assignment like `if (a*b = c) {`. I find it a little paranoid, nevertheless I have been following this advice. It seems to me that returning const objects can degrade performance in C++11. ``` #include <iostream> using namespace std; class C { public: C() : v(nullptr) { } C& operator=(const C& other) { cout << "copy" << endl; // copy contents of v[] return *this; } C& operator=(C&& other) { cout << "move" << endl; v = other.v, other.v = nullptr; return *this; } private: int* v; }; const C const_is_returned() { return C(); } C nonconst_is_returned() { return C(); } int main(int argc, char* argv[]) { C c; c = const_is_returned(); c = nonconst_is_returned(); return 0; } ``` This prints: ``` copy move ``` Do I implement the move assignment correctly? Or I simply shouldn't return const objects anymore in C++11?

Original source

Related problems