【问题标题】:Warn if accessing moved object in C++11 [duplicate]如果在 C++11 中访问移动对象时发出警告 [重复]
【发布时间】:2013-01-11 05:45:27
【问题描述】:

可能重复:
What can I do with a moved-from object?

在您调用std::move 并将结果传递给函数后,您通常必须假设稍后访问移动的对象将导致未定义的行为。

是否有工具可以检测这些访问并警告您。例如:

{
  Widget w;
  foo(std::move(w));
  // w may be undefined at this point

  w.doSomething(); // WARN
}

至少,gcc 4.7.2 和 clang 3.2 和 -Wall 不会抱怨。

更新:回顾这个问题,关键是编译器无法判断一个对象在被移出后是否仍然有效。如果提议N4034: Destructive Move 被接受,我希望编译器有更多选择(但前提是移动是破坏性的)。

【问题讨论】:

  • 您确定它会导致未定义的行为吗?我的理解是该对象处于有效但未指定的状态,这可能不会导致 UB。
  • 这不是 UB。不过,具体细节必须由您的班级记录。
  • @JesseGood:我不认为这是重复的。他似乎知道他能做什么,他只是想要一些诊断以确保他没有这样做。但在一般情况下,我认为这没有意义
  • “稍后访问移动的对象将导致未定义的行为” - 而且,正如其他人所说,这个假设是错误的,这反过来也是为什么一般关于访问已移动对象的警告没有意义,因为编译器本身不知道对象的哪些方法在移动后可以安全访问。
  • @PhilippClaßen:您要求提供工具支持。但是警告是错误的,因为编译器无法知道。使用从对象移动的不是先验错误。在大多数情况下,这甚至都没有错。这是合法的事情,编译器不应该警告它。

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


【解决方案1】:

他们也不应该。搬出班级的行为是你想要的。这不是编译器应该警告的事情。

对于标准库对象,移出的类处于“有效但未指定的状态”。因此,这样做是完全合法的:

std::vector<int> v{20, 30, 40};
std::vector<int> v2 = std::move(v);
v = std::vector<int>{50, 60, 70, 80};

clear 不关心向量的当前状态是什么;它只是清除向量。因此,它被重置为已知状态。同样,operator= 不关心当前状态是什么;它会将其重置为已知状态。

【讨论】:

  • 当然,这种用法应该是安全的,但您正在重新初始化对象 (operator=)。那么,如果您改为调用v.size() 会怎样。我不知道它是否保证返回0,所以我仍然认为在这里发出警告是个好主意。
  • v.size() 不保证返回0,而是返回容器的实际大小。在某些情况下,尝试的移动可能会变成副本,并且源可能没有改变。例如,从int 移动可能不会使源的值为零。
  • @PhilippClaßen 好吧,size 可能不能保证返回 0,但也不是 UB 调用 size 并使用其返回值。编译器只是不太了解您的对象用例或其方法的先决条件,无法说您在访问它时出错了。我不希望仅仅因为编译器认为我很愚蠢而对明显正确且完美定义(按标准)的代码发出警告。
  • @PhilippClaßen 但是好吧,在标准库组件的情况下,编译器确实可以知道其方法的先决条件,并且在访问需要特定定义状态的方法时确实可以发出警告(例如front或pop_back) 移动后。但这对编译器的要求可能有点高,更重要的是,除了仅仅是库组件之外,还需要 "compiler magic" 支持标准库(并且不会工作对于自定义类型,无论如何)。
猜你喜欢
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 2019-03-16
  • 2014-06-25
  • 1970-01-01
  • 2012-05-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多