Search code examples
c++c++11move-semanticsstdmove

Why std::move don't change source variable to default value in default move constructor?


I try to understand the move constructor.

I allocate memory in the class' constructor and destroy it in the destructor.

When I try to move the class, I still have a double free.

#include <algorithm>

class TestClass
{
 public:
  TestClass() {a_ = new int[1];}
  TestClass(TestClass const& other) = delete;
  TestClass(TestClass && other) noexcept // = default;
  {
    this->a_ = std::move(other.a_);
  }
  ~TestClass() {delete[] a_;}
 private:
  int* a_ = nullptr;
};

int main( int argc, char** argv )
{
  TestClass t;
  TestClass t2 = std::move(t);
}

Why std::move do not change to nullptr other.a_ ?

I have the same problem if the move constructor is default.

I found the following questions but I still don't know why the move operator don't change the source variable to default value.

How does std::move invalidates the value of original variable?

C++ how to move object to a nullptr

C++ std::move a pointer


Solution

  • std::move just produces an rvalue (xvalue); it won't perform move operation, it won't modify the argument at all.

    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.

    Given this->a_ = std::move(other.a_);, as built-in type, i.e. int*, this->a_ is just copy-assigned from ohter.a_, then both the pointers point to the same object. The defaulted move constructor does the same thing in fact. (It performs member-wise move operation on the data members; note that for built-in types the effect of move is same as copy.)

    You need to set other.a_ to nullptr explicitly if you want to define that after moved the object should contain a null pointer.

    E.g.

    TestClass(TestClass && other) noexcept
    {
      this->a_ = other.a_;
      other.a_ = nullptr;
    }