【问题标题】:std::move- How to warn programmer not to use *moved from* objectstd::move- 如何警告程序员不要使用 *moved from* 对象
【发布时间】:2017-02-14 01:50:47
【问题描述】:

假设有这样一个函数:

int * func()
{
  std::unique_ptr<int> ptr(new int(3));
  //Few more lines of code

  //then one function added where programmer writes like some thing

  SOME_OTHER_FUNC(std::move(ptr));

  return ptr.get();
}



void SOME_OTHER_FUNC(std::unique_ptr<int> arg_ptr)
{
}

有没有办法警告程序员避免std::move 出现此类错误?这不仅仅是关于unique_ptr,也适用于其他对象。

当我们不恰当地使用 moved-from 对象时,是否有任何机制生成警告?

【问题讨论】:

  • 不确定是否重复但关闭主题明智:stackoverflow.com/questions/39413502/…
  • 我希望编译器编写者针对使用已被强制转换为右值的任何内容(例如 std::move)提出警告。如果它对您造成的伤害足够大,请考虑向您的编译器作者提交补丁!
  • @TobySpeight 我怀疑会引入这样的警告。类型可以具有移动构造函数/赋值运算符,使原始构造函数处于(部分,甚至全部)指定状态,并且某些(甚至可能全部)操作将具有明确定义的行为。编译器如何知道使用 move from object 是否是无意的?
  • 引自 LLVM 周刊:引入了新的clang-tidy 检查,misc-use-after-move。如果对象在移动后被使用,则会发出警告r281453。

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


【解决方案1】:

std::move 是警告。如果你的程序员不理解这一点,你必须更好地教育他们。如果函数太长以至于程序员可以合理地忽略移动,则需要重构函数以使其更短。

【讨论】:

  • 或者,限制move'd from 变量的范围,因此它的生命周期结束和开始就在它被移动的位置旁边。
  • "std::move 是警告。" 据说委员会费了很大的力气才强迫你使用std::move 以确保每个阅读代码的人都清楚该对象已被移出。有些人仍然不明白。
  • @NicolBolas 大家都知道std::move不动,std::forward不转发。
【解决方案2】:

并非所有问题都可以或应该在源代码中解决。

  1. 使用unique_ptr 是一个实现细节;把它封装起来。

  2. 为功能和使用测试指定前置条件和后置条件。

【讨论】:

  • 不是每个问题都可以通过抽象来解决。您的资源可以被移出并在之后变得无效的事实无法通过抽象来解决。完美的测试和测试覆盖可以解决所有问题,就像编写完美的代码可以解决所有问题一样。更完美的测试和更完美的代码会让事情变得更好,但是说“编写测试来覆盖这个”与“一开始就不要这样做”一样有用。
【解决方案3】:

如果有编译器的帮助会很好,不是吗?它并不像您想象的那么简单,这是有充分理由的:

  1. std::move() 并不神奇,您可以编写自己的类似函数。编译器如何知道您的新函数必须以同样的方式处理?您需要一个标准属性来装饰函数。如果您针对确切的函数 std::move 发出警告,则您会将标准库的知识编码到语言编译器中¹。
  2. 虽然一般而言,移出对象只能被分配或销毁,但某些类可能对移出状态提供更强的保证(例如,容器可以记录为成为移动时有效的空集合)。你如何告诉编译器在特定的移动对象上哪些操作是安全的?

¹ 反驳:编译器在验证 std::printf() 和 std::scanf() 函数族的格式字符串时当然已经做了类似的事情。

【讨论】:

    猜你喜欢
    • 2020-11-04
    • 2017-04-02
    • 1970-01-01
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    相关资源
    最近更新 更多