0

I was testing my knowledge in C++ and have encountered a problem. Consider this code:

class A
{
public:
    A(int n = 0)
            : m_n(n)
    {
        std::cout << 'd';
    }

    A(const A& a)
            : m_n(a.m_n)
    {
        std::cout << 'c';
    }

    A(A&& a){
        std::cout<<'r';
    }

private:
    int m_n;
};


int main()
{
    A a = A();
    std::cout << std::endl;

    return 0;
}

Clearly, the A() constructor is an rvalue, as no permanent object has been created. So I think that first I have to see "d" as output. Then we are copying the rvalue to our new object, which is yet to be initialised. I have implemented a copy constructor that accepts an rvalue as an argument but I did not see the proof (no "r" output).

Can someone explain why that is?

melpomene
  • 84,125
  • 8
  • 85
  • 148

1 Answers1

1

You're seeing a form of copy elision -- the compiler is actually required to optimize and implement A a = A() by initializing a directly with the arguments to the constructor expression (() in this case) rather than creating a temporary and copying it into a. If you want to enforce an unnamed object to be copied, you need to initialize a with an expression that is not a simple constructor call.

Note that even then, the compiler may elide construtor calls by the as-if rule (if the only visible side effects are in the copy/move constructors/destructors. Your best bet to "force" a call to the move ctor is to use a named value and std::move:

A a1;
A a2 = std::move(a1);
Chris Dodd
  • 119,907
  • 13
  • 134
  • 226