为什么函数中变量的最后一个赋值不能被视为移动?

Why can't the last assignment from a variable in a function be treated as a move?

本文关键字:移动 不能 赋值 函数 变量 最后一个 为什么      更新时间:2023-10-16

在如下代码中:

class X {
  X(const X&) {
    // ...
  }
  X(const X&&) {
    // ...
  }
  // ...
};
void f() {
  X a;
  // ...
  X b = a;
  // ... code that doesn't use a
}

我的理解是最后一个语句调用复制构造函数而不是移动构造函数。假设af()中不再使用,编译器可以自动优化此语句以使用move构造函数代替吗?

注:我知道std::move(),但我问的是自动移动

您需要编写一个规范,以某种方式正确处理

void f() {
  X a;
  g(a); // stash a reference to a somewhere 
  X b = a; // can't move from a!
  g2(); // use the reference stored by g
}

对于安全的移动,您需要证明后续代码,包括它调用的所有函数,不直接或间接访问a,这在一般情况下是不可能的,因为这些函数的定义可能对编译器不可用(例如,在不同的翻译单元中)。

编译器很难/不可能知道a是未引用的,除非在一些平凡的场景中。任何外部函数都可以保存指向a的指针或引用,并且任何外部函数都可以依赖于该指针的内容。

在不涉及外部函数的情况下,我猜优化是可能的。

如果没有更严格的分析,优化将不是完全安全的。例如,一个局部对象可能已经用a的地址进行了初始化,并在销毁时对它做了一些操作,这将发生在最后一条语句X b = a;之后。