23

std::move对象上调用之后,如果在之后使用对象,为什么语言不会导致编译错误?

是因为编译器无法检测到这种情况吗?

4

5 回答 5

11

C++ 语言设计的一般原则是“信任程序员”。我能想到的一些问题是在对象成为std::move.

  • 在一般情况下,确定给定的使用是否在调用之后std::move相当于解决停止问题。(换句话说,它不能完成。)您必须想出一些规则,以一种可以静态确定的方式来描述“之后”的含义。
  • 一般来说,分配给作为参数的对象是完全安全的std::move。(一个特定的类可能会导致一个断言,但那将是一个非常奇怪的设计。)
  • 编译器很难判断给定函数是否只会为类的元素分配新值。
于 2017-03-14T20:22:21.433 回答
7

请记住,std::move只不过是对右值引用的强制转换。它本身实际上并没有移动任何东西。此外,该语言仅声明从对象移动的对象处于有效/可破坏状态,但除此之外并没有说明其内容 - 它可能仍然是完整的,它可能不是或(就像std::unique_ptr它可能被定义为具体内容 ( nullptr)) - 这一切都取决于移动构造函数/移动分配操作符实现的内容。

因此,访问从对象移动的对象是否安全/有效完全取决于特定对象。移动后阅读 a std::unique_ptr,看看它是否nullptr非常好,例如 - 对于其他类型;没那么多。

于 2017-03-14T20:21:21.383 回答
4

这是因为我们经常想使用移动的对象。考虑以下的默认实现std::swap

template<typename T> 
void swap(T& t1, T& t2)
{
    T temp = std::move(t1);
    t1 = std::move(t2);   // using moved-from t1
    t2 = std::move(temp); // using moved-from t2
}

您不希望编译器在每次使用std::swap.

于 2017-03-15T09:13:37.810 回答
4

这就是所谓的“实现质量”问题:对于一个好的编译器或工具链来说,对潜在危险的移动后使用情况发出警告比语言标准以精确定义的形式正式禁止它更有意义。一组情况。毕竟,移动后的某些使用是合法的(例如 a 的情况,std::unique_ptr从移动后保证为空),而其他未定义的情况则不容易检测到——一般来说,检测一个对象是否被使用在它被移动之后相当于停止问题。

您可以使用 clang-tidy 来检测移动后的使用:https ://clang.llvm.org/extra/clang-tidy/checks/misc-use-after-move.html

于 2017-03-14T20:21:43.390 回答
1

对象的移动后状态的性质由实现者定义;在某些情况下,移动对象可能会使其处于完全可用的状态,而在其他情况下,对象可能会变得无用(或者更糟糕的是,使用起来有些危险)。

虽然我有点同意 - 最好有生成警告的选项,至少,如果一个对象在移动后以潜在危险的方式使用,我不知道 GCC 或 Clang 的选项来引起注意对于这种类型的代码气味。

(事实上​​,对于勇敢的人来说,这可能会成为一个很好的基础,例如Clang 插件,确实!)

于 2017-03-14T20:20:41.777 回答