Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't object returned by std::move destroyed immediately

Tags:

c++

c++11

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
like image 341
Pony279 Avatar asked Mar 27 '13 16:03

Pony279


2 Answers

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.

like image 95
Steve Jessop Avatar answered Oct 17 '22 03:10

Steve Jessop


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
like image 36
Pete Becker Avatar answered Oct 17 '22 03:10

Pete Becker