JeanPhi
JeanPhi

Reputation: 127

Move semantics and constructors when dereferencing a new

I have the following code (http://coliru.stacked-crooked.com/a/a0e5ff6ee73634ee):

#include <iostream    

class A {
  public:
  explicit A(int a)         {std::cout << "Main constructor" << std::endl;}
  A(const A& a)             {std::cout << "Copy constructor" << std::endl;}
  A& operator =(const A& a) {std::cout << "Copy assignment" << std::endl; return *this;}
  A(A&& a)                  {std::cout << "Move constructor" << std::endl;}
  A& operator =(A&& a)      {std::cout << "Move assignemnt" << std::endl; return *this;}
};

int main(void) {
    std::cout << "\nA a3(A(0))" << std::endl;
    A a3(A(0));
    std::cout << "\nA a31(std::move(A(0)))" << std::endl;
    A a31(std::move(A(0)));
    std::cout << "\nA a4(*(new A(0)))" << std::endl;
    A a4(*(new A(0)));
    std::cout << "\nA a41(std::move(*(new A(0))))" << std::endl;
    A a41(std::move(*(new A(0))));
}

This code writes the following:

A a3(A(0))
Main constructor  

-> After having read Move semantics and copy constructor I assume RVO happened and a3 takes over the content of the construction of A(0).

A a31(std::move(A(0)))
Main constructor
Move constructor   

-> OK

A a4(*(new A(0)))
Main constructor
Copy constructor    

-> Why is not this a move constructor instead of the Copy constructor ?

A a41(std::move(*(new A(0))))
Main constructor
Move constructor  

-> OK
EDIT: After analyzing the problem a little deeper I realized that actually @sameerkn is right. However as @Angew suggested I tried to analyze what is happening with a static variable: such variables are not moved as one could expect (they seem to be treated as const variables). See here full code: http://melpon.org/wandbox/permlink/RCntHB9dcefv93ID

Following code:

A a1(testStatic(1));
A a2(std::move(*(a1.getPointer())));  <-- Moving a dereference
std::cout << "\na1.mValue = " << a1.mValue << std::endl;
std::cout << "a2.mValue = " << a2.mValue << std::endl;

Will return:

Main constructor: This is my long String that should not be SSOed [STATIC]
Copy constructor: This is my long String that should not be SSOed [STATIC]
return aLocal
Move constructor  <-- The dereferenced pointer is moved as expected
Destructor: [mValue moved away]   <-- See here that the string was moved away
Move constructor  <-- Moved again because of std::move

Upvotes: 2

Views: 840

Answers (2)

sameerkn
sameerkn

Reputation: 2259

new A(0);

Creating an object via "new". (NOTE: Its creating a pure object which has an identity which can be identified by the address returned by "new" in code and this object is available to rest to the code for its utilization and in no sense a temporary nameless object.)

And move semantic work on purely temporary object whose identity is not available for utilization.

Upvotes: 1

A a4(*(new A(0)))
Main constructor
Copy constructor    

-> Why is not this a move constructor instead of the Copy constructor ?

Because dereferencing a pointer gives an lvalue reference. The fact that the pointer itself is an rvalue plays no role—and why should it? You can very easily have an rvalue pointer pointing to something that is most definitely not an rvalue. Example:

std::string s{"42"};

std::string* getPointer()
{
  return &s;
}

int main()
{
  std::string x(*getPointer());
  std::cout << s;
}

The pointer returned by getPointer is an rvalue, just as the pointer returned by new A. But you certainly would not expect the code to move the contents of s into x, would you?

Upvotes: 8

Related Questions