I recently started using c++ and I chose to learn c++11 features. But how c++ codes run is sometimes not so tangible.
below is my code.
At the part with decltype(std::move(sample)) sample2 = std::move(sample);
I'm not sure why this line doesn't call move constructor.
Could you explain why?
#include <iostream>
class AAA
{
public:
AAA() { std::cout << "default constructor" << std::endl; }
AAA(const AAA& cs) { std::cout << "copy constructor" << std::endl; }
AAA(AAA&& cs) { std::cout << "move constructor" << std::endl; }
~AAA() { std::cout << "destructor" << std::endl; }
};
int main(int argc, char* args[])
{
AAA sample;
// ((right here))
decltype(std::move(sample)) sample2 = std::move(sample);
return 0;
}
It is compiled on [ ubuntu 16.04 LTS ] with [ gcc 5.4.0 ]
original code : https://ide.geeksforgeeks.org/tALvLuSNbN
No move constructor is automatically generated.
std::move. std::move is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object. In particular, std::move produces an xvalue expression that identifies its argument t . It is exactly equivalent to a static_cast to an rvalue reference type.
A move constructor allows the resources owned by an rvalue object to be moved into an lvalue without creating its copy. An rvalue is an expression that does not have any memory address, and an lvalue is an expression with a memory address.
The function std::move<T>
returns a T &&
, so for std::move(sample)
it returns AAA &&
. This is an rvalue reference and behave a lot like an lvalue reference (a type like AAA &
would be an lvalue reference) in that they both are alias to objects that already exist.
It's important to understand that std::move
does not in itself cause anything to be moved. It simply returns an rvalue reference to the argument it's given. For example std::move(foo);
alone does absolutely nothing. It's only when the result is used to initialize or assign to an object that it becomes useful.
For example auto bar = std::move(foo);
will return an rvalue reference to foo
and use that reference to call bar
's constructor.
To answer the question, since std::move(sample)
returns a AAA &&
, the line in question is the same as AAA && sample2 = std::move(sample);
. The behavior is practically the same as AAA & sample2 = sample;
. In both cases, you are initializing a reference to an existing object and no new object needs to be constructed.
If your goal is to move sample
into a new AAA
, the correct line would be auto sample2 = std::move(sample);
like you do with sample3
. Though beware that the line sample3
is moving from an already moved-from sample
.
Your snippet expands to
AAA&& sample2 = std::move(sample);
which binds an rvalue (the result of std::move(sample)
) to an rvalue reference (sample2
). No new object is constructed, and hence no such constructor is called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With