【问题标题】:Why std::move don't change source variable to default value in default move constructor?为什么 std::move 不将源变量更改为默认移动构造函数中的默认值?
【发布时间】:2020-08-28 14:42:15
【问题描述】:

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

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

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

#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_

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

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

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

C++ how to move object to a nullptr

C++ std::move a pointer

【问题讨论】:

  • 在你的移动构造函数中,你忘记了other.a_ = nullptr;。或者通过std::swap(this_&gt;a_, other.a_);.
  • 在 C++14 及更高版本中,您将使用 std::exchange 来初始化 a_
  • 我认为这是某种培训,这就是为什么您不使用std::vector,它会以最好的方式做到这一点。
  • 是的,它是 POC。我想了解移动构造函数/赋值的默认实现是什么,并知道何时需要使用默认或自定义实现。
  • @VincentLEGARREC std::move() 只是一个类型转换,您试图“移动”到原始指针,而不是使用移动构造函数或移动赋值运算符的可移动类型。这实际上是一个复制分配,因此没有调用代码来实际将输入指针重置为nullptr

标签: c++ c++11 move-semantics stdmove


【解决方案1】:

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

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

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

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

例如

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

【讨论】:

  • 谢谢。那么,默认复制构造函数和默认移动构造函数有什么区别(除了一个使用 const ref 而另一个使用非 const rvalue)?
  • @VincentLEGARREC 对于内置类型数据成员,它们具有相同的效果。都是类类型的数据成员,都会对数据成员调用copy-constructor或者move-constructor,那么效果取决于数据成员的构造函数是如何实现的。
【解决方案2】:

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

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

您需要明确地进行清除。

或者,更简单,只需使用std::unique_ptr&lt;int&gt; a_。这样你就不需要定义任何特殊的成员函数,类的行为就如你所想。

【讨论】:

    猜你喜欢
    • 2022-01-09
    • 2020-03-24
    • 2020-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-07
    • 2013-03-16
    • 2019-08-09
    相关资源
    最近更新 更多