I tested the following code:
#include <iostream>
using namespace std;
class foo{
public:
foo() {cout<<"foo()"<<endl;}
~foo() {cout<<"~foo()"<<endl;}
};
int main()
{
foo f;
move(f);
cout<<"statement \"move(f);\" done."<<endl;
return 0;
}
The output was:
foo()
statement "move(f);" done.
~foo()
However, I expected:
foo()
~foo()
statement "move(f);" done.
According to the source code of the function move:
template<typename _Tp>
constexpr typename std::remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
The returned object is a right value, So Why isn't it destroyed immediately?
-----------------------------------------------------------------
I think I just confused rvalue and rvalue reference.
I modified my code:
#include <iostream>
template<typename _Tp>
constexpr typename /**/std::remove_reference<_Tp>::type /* no && */
/**/ mymove /**/ (_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
using namespace std;
class foo{
public:
foo() {cout<<"foo() at "<<this<<endl;} /* use address to trace different objects */
~foo() {cout<<"~foo() at "<<this<<endl;} /* use address to trace different objects */
};
int main()
{
foo f;
mymove(f);
cout<<"statement \"mymove(f);\" done."<<endl;
return 0;
}
And now I get what I've been expecting:
foo() at 0x22fefe
~foo() at 0x22feff
statement "mymove(f);" done.
~foo() at 0x22fefe
Moving from an object doesn't change its lifetime, only its current value. Your object foo
is destroyed on return from main
, which is after your output.
Futhermore, std::move
doesn't move from the object. It just returns an rvalue reference whose referand is the object, making it possible to move from the object.
Objects get destroyed when they go out of scope. Moving from an object doesn't change that; depending on what the move constructor or move assignment operator does, the state of the object can be different after the move, but is hasn't yet been destroyed, so the practical rule is that moving from an object must leave it in a state that can be destroyed.
Beyond that, as @R.MartinhoFernandes points out, std::move
doesn't do anything. It's the object's move constructor or move assignment operator that does whatever needs to be done, and that isn't applied in a call to std::move
; it's applied when the moved-from object is used to construct a new object (move constructor) or is assigned to an existing object (move assignment operator). Like this:
foo f;
foo f1(f); // applies foo's copy constructor
foo f2(std::move(f)); // applies foo's move constructor
foo f3, f4;
f3 = f; // applies foo's copy assignment operator
f4 = std::move(f1); // applies foo's move assignment operator
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