Reputation: 787
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
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