Wubin Ouyang
Wubin Ouyang

Reputation: 787

Why I can't move this vector in the copy constructor of my custom class?

class TestClass 
{
  public:
  TestClass(){
      cout<<"constructor"<<endl;
      p = {1,2,3};
      cout<<(unsigned int *)(this->p.data())<<endl;
  }
  TestClass(const TestClass& test):  p(std::move(test.p))
  {
      cout <<"copy constructor"<<endl;
      cout<<(unsigned int *)(this->p.data())<<endl;

  }
  TestClass(TestClass && test): p(std::move(test.p))
  {
      cout <<"move constructor"<<endl;
      cout<<(unsigned int *)(this->p.data())<<endl;
  }
  private:
      std::vector<int> p;
};


int main()
{
  TestClass t{};
  TestClass p{t};
  TestClass s{std::move(p)};
  return 0;
}

And the output is

 constructor
 0xb92bf0
 copy constructor
 0xb915b0
 move constructor
 0xb915b0

I am just wondering why the address below constructor is different from the one below copy constructor. From what I understand, even it is a copy constructor, but I used std::move to get a rvalue reference and vector's move constructor should be called, so they should be same object.

Upvotes: 3

Views: 256

Answers (1)

M&#225;rio Feroldi
M&#225;rio Feroldi

Reputation: 3591

std::move just casts whatever is passed to it to an xvalue, so rvalue-references can bind to it and may steal its resources. Here:

TestClass(const TestClass& test):  p(std::move(test.p))

std::move will produce an expression of type const std::vector<int> &&, which, as you can see, has a const qualifier. If you check the copy- and move-constructors of std::vector on [vector], you'll see that the move-constructor expects an expression of type std::vector<T> &&, and the copy-constructor expects a const std::vector<T> &:

vector(const vector& x);
vector(vector&&) noexcept;

Compare the result of std::move(test.p) to these two constructors. Because an rvalue-reference doesn't bind to types with const qualifiers (unless the rvalue-reference is const-qualified), then the move-constructor overload isn't a good candidate. The other candidate (copy-constructor) does accept a const-qualified type, and since xvalues have the same properties as rvalues:

http://en.cppreference.com/w/cpp/language/value_category#rvalue

An rvalue may be used to initialize a const lvalue reference, in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends.

, the copy-constructor is a good candidate and is selected.

Upvotes: 4

Related Questions