警告 C26800

使用已移动的对象:“object”。

注解

如果在变量被移走的情况下使用变量,则会触发警告 C26800。 变量在作为 rvalue 引用传递给函数后被视为已移动。 对于赋值、析构函数和一些状态重置函数(如 std::vector::clear),有一些例外情况。 使用状态重置函数后,我们可以使用变量。 这只会检查与局部变量有关的原因。

以下方法被视为状态重置方法:

  • 名称中包含以下不区分大小写 substring 的函数:clearcleanresetfreedestroyreleasedeallocassign
  • 重载赋值运算符、析构函数

此检查遵循 std::swap 操作:

void f() {
    Y y1, y2;
    consume(std::move(y1));
    std::swap(y1, y2);
    y1.method();                  // OK, valid after swap.
    y2.method();                  // warning C26800
}

该检查还支持 STL 中有条件地移动其自变量的 try_emplace 操作:

int g() {
  std::map<int, Y> m;
  Y val;
  auto emplRes = m.try_emplace(1, std::move(val));
  if (!emplRes.second) {
    val.method();  // No C26800, val was not moved because the insertion did not happen.
  }
}

代码分析名称:USE_OF_A_MOVED_FROM_OBJECT

示例

以下代码生成 C26800。

#include <utility>

struct X {
    X();
    X(const X&);
    X(X&&);
    X &operator=(X&);
    X &operator=(X&&);
    ~X();
};

template<typename T>
void use_cref(const T&);

void test() {
    X x1;
    X x2 = std::move(x1);
    use_cref(x1);                // warning C26800
}

以下代码不会生成 C26800。

#include <utility>

struct MoveOnly {
    MoveOnly();
    MoveOnly(MoveOnly&) = delete;
    MoveOnly(MoveOnly&&);
    MoveOnly &operator=(MoveOnly&) = delete;
    MoveOnly &operator=(MoveOnly&&);
    ~MoveOnly();
};

template<typename T>
void use(T);

void test() {
    MoveOnly x;
    use(std::move(x)); // no 26800
}