【问题标题】:Why doesn't moving an object leave it null?为什么不移动对象使其为空?
【发布时间】:2018-08-06 12:46:28
【问题描述】:
A a5(move(a1));

虽然移动后 a1 的成员变量设置为默认值,但 a1 本身并未设置为 null。您不能执行 a1 == nullptr... 来检查 a1 是否无用...

我觉得这很奇怪。我在这里有什么误解吗?我认为如果 a1 被移动,它将变得无用,这应该通过以某种方式将其设置为 null 来表示。没有?

问题是,通过将 a1 保留为非 null 状态,它仍然可以使用。没有编译器警告或错误。没有真正的迹象表明该对象处于混乱状态。如果 a 有两个成员 var,一个 int 和一个动态 alloc 对象,则 dyn alloc 对象将指向 nullptr 但 int 将有一个 def 值(当然只有在正确实施的情况下......容易搞砸)。

所以搬家后就可以了

int number = a1.getInt();

并取回一个没有意识到 a1 已被重置的数字。在 C 和 C++ 中,我们被教导在其资源被盗时将指针设置为 null(a.k.a nullptr 或 NULL)以消除这种混淆。随着引入移动窃取对象资源的功能,是否没有内置机制或最佳实践来指示对象已被窃取并因此“重置”为默认构造状态?

编辑 添加了示例移动 c'tor

A(A&& other) : num(other.num), s(other.s){
   other.num = 0;
   other.s = nullptr;     //dyn alloc obj
}

【问题讨论】:

  • C++ 没有像其他语言一样将对象设置为“null”的通用方法。通常moveing 一个对象要么复制它,要么让它处于“空”状态,但这完全取决于实现
  • “Null”在 C++ 中不是一个通用的东西。
  • 移动操作的要求是使对象处于可以安全销毁的有效但未指定的状态。不要求它使对象处于“空”或“空”状态。
  • 那么有没有办法知道或检查一个对象是否被盗?

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


【解决方案1】:

为什么不移动一个对象让它为空?

因为如果对象不是指针,那么它一般不会有“空状态”,所以不能“让它为空”;如果它是一个指针,当你从它“移动”时不要让它为空。

让 a1 处于非空状态,它仍然可以使用。没有编译器警告或错误。没有真正的迹象表明该对象处于混乱状态...

它不是处于混乱状态,而是处于valid state。但是,当您使用移动后对象的移动后值时,发出警告也许不是一个坏主意。

【讨论】:

  • 我也认为有一些警告或检查是个好主意。但显然,要么人们不理解这个问题,要么认为考虑到否决票不是一个好主意。当人们没有任何解释地投票时,您不只是喜欢它吗?
  • @code:在我看来,StackOverflow 上有一种糟糕的投票文化。人们出于各种不相关的原因对您投了反对票 - 而不是标记;因为你误解了一些东西(这就是询问的全部内容);等等。另请参阅this
  • 话虽如此 - 你的问题措辞不佳 - 你没有解释 A 和 a1 来自哪里等等。
【解决方案2】:

移动操作的结果应该使对象处于有效但未指定的状态。通常,如果要销毁对象或为对象分配新值,您会移动。移出对象后,您通常不会尝试使用它。

a1 类型的移动构造函数负责执行移动并将对象保持在您希望的状态。 如果默认生成的移动构造函数的行为与您不同想那么你可以为对象编写自己的移动构造函数。例如,您可以在此移动构造函数中设置一个指向 null 的指针。或者您可以设置一个标志,指示该对象处于已移出状态。

在您的问题中,您“希望”的行为更像是与空对象交换的行为。也许下面的代码更适合你:

A a5{};
using std::swap;
swap(a5, a1);

关于建议other.s 指向“dyn alloc obj”的更新:您应该避免这样做,因为这意味着您必须浪费时间编写复制构造函数、移动构造函数、复制赋值运算符、移动-赋值运算符和析构函数。

在这里,你是你自己死亡的建筑师:通过将此指针引入你的类,你就会制造出你抱怨的移动问题。

相反,任何拥有的资源都应由其自己的类管理。标准库的 std::unique_ptr 足以满足许多此类用例。

【讨论】:

  • 谢谢,虽然我同意你在这里所说的,我已经知道了。尊敬的,这不是我要问的。我在问是否有办法知道或检查对象是否被盗?
  • @code 你的问题标题是“为什么不移动一个对象让它为空?”,而不是“我怎么知道一个对象是否已经被移动了?”。我用粗体表示了我的回答中涵盖这个其他问题的部分。
  • 谢谢MM。也许标题并不理想,但如果您阅读它,整个问题是关于由于无法识别被盗对象而导致的潜在误用移动后操作。
  • @code 是的,我在回答中解决了这个问题并解释了你应该做什么
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-19
  • 2014-06-21
  • 1970-01-01
  • 2022-08-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多