2

我试图理解移动构造函数。

我在类的构造函数中分配内存并在析构函数中销毁它。

当我尝试移动班级时,我仍然有双倍免费。

#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);
}

为什么std::move不更改为 nullptr other.a_

如果移动构造函数是默认的,我也会遇到同样的问题。

我发现了以下问题,但我仍然不知道为什么移动运算符不将源变量更改为默认值。

std::move 如何使原始变量的值无效?

C ++如何将对象移动到nullptr

C++ std::move 指针

4

2 回答 2

6

std::move只产生一个右值(xvalue);它不会执行移动操作,它根本不会修改参数。

特别是,std::move生成一个标识其参数的 xvalue 表达式t。它完全等同于static_cast右值引用类型。

给定this->a_ = std::move(other.a_);,作为内置类型,即int*this->a_只是从 复制分配ohter.a_,那么两个指针都指向同一个对象。默认的移动构造函数实际上做同样的事情。(它对数据成员执行逐个成员的移动操作;请注意,对于内置类型,移动的效果与复制相同。)

如果要在移动后定义对象应包含空指针,则需要显式other.a_设置。nullptr

例如

TestClass(TestClass && other) noexcept
{
  this->a_ = other.a_;
  other.a_ = nullptr;
}
于 2020-05-12T16:44:33.820 回答
2

首先,std::move只是一个导致other.a_被视为右值的演员表。对于指针,移动只是一个副本。

我认为是这样,因为并非在所有情况下都需要清除源指针,并且在不需要它的情况下会导致开销。

您需要明确地进行清理。

或者,更简单,只需使用std::unique_ptr<int> a_. 然后你不需要定义任何特殊的成员函数,并且类的行为就像你想象的那样。

于 2020-05-12T16:45:41.040 回答