0

Here is the code: http://coliru.stacked-crooked.com/a/f7731b48747c61a9

#include <iostream>

struct A{
    A(const A&){ std::cout << "A(const A&)" << std::endl;}
    A(const A&&){ std::cout << "A(const A&&)" << std::endl;}
    A(){ }
};

A foo(){
    return *new A;
}
int main()
{
    A a;
    A c(foo());
}

Since, I passed to the c's constructor argument a temporary object, I expected the move constructor to be called. But the copy constructor was. Why?

stella
  • 2,546
  • 2
  • 18
  • 33
  • 2
    I'm fairly sure "const r-value reference" (`const &&`)is nonsensical in the general sense. R-value reference handling is done to explicitly alter the argument passed (reducing it to an empty shell usually, taking all resources from it to populate a different object); if you don't modify it, then just accept a const l-value reference (`const &`) and be done with it. – ShadowRanger Oct 29 '15 at 04:17
  • 3
    [With -fno-elide-constructors added](http://coliru.stacked-crooked.com/a/7b7181af77a7c4ce) – chris Oct 29 '15 at 04:27

1 Answers1

4

Since foo returns a non-constant rvalue, it cannot bind to the const-rvalue reference. The copy constructor is the only remaining viable overload.

A constructor that would be a better overload than the copy constructor would be:

A(A&&);

Additionally, either constructor (copy or move) may be elided under the rules of copy elision (e.g. see here or here.)

Community
  • 1
  • 1
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • @stella I think the problem is with the *memory leak operator* `*new`, the compiler is not eliding copying that to the return value. Replace that with `return {};` and you won't see anything printed. – Praetorian Oct 29 '15 at 04:27
  • @stella: Added note on copy elision. – Kerrek SB Oct 29 '15 at 07:12