Search code examples
c++constructorcopy-constructorrvo

Why is a public copy-constructor required when assigning the temporary return object to a reference?


Consider the following code:

class MyClass
{
    MyClass()
    {
        x = 0;
    }
    MyClass(const MyClass&)
    {
        x = 1;
    }
public:
    int x;
    MyClass(MyClass&&)
    {
        x = 2;
    }
    static const MyClass f()
    {
        return MyClass();
    }
};

int main()
{
    const MyClass& p = MyClass::f();
    return 0;
}

This code does not compile on VC++ 2010.

error C2248: 'MyClass::MyClass: cannot access private member declared in class 'MyClass'

I believe it has something to do with the RVO, but I'd like to better understand what it's doing. I see no reason the copy constructor must be called.

Here's what I would expect:

  • Enter f()
  • Call default constructor
  • Call move constructor to return the object (possibly optimized out by RVO)
  • Assign temporary return object to the reference p

In fact, if I make the copy constructor public, it compiles and works exactly that way. The copy constructor is never called. The final value of x is 0.


Solution

  • This has to do with C++03 rules. In C++03, assigning initially a temporary to a reference may copy the temporary.

    Starting with C++11, that behavior is gone and no copy is done anymore.