移动赋值给self的行为

Behaviour of move-assignment to self

本文关键字:self 赋值 移动      更新时间:2023-10-16

示例代码:

#include <iostream>
int main()
{   
    std::vector<int> w(20, 123), x;
    w = std::move(w);
    std::cout << w.size() << std::endl;
}

g++ 4.8.3: 0

当然,标准规定移动赋值操作符使操作数处于未指定状态。例如,如果代码是x = std::move(w);,那么我们期望w.size()为零。

然而,是否有一个指定的订购或其他条款涵盖自移动情况?是否未指定大小是020,或其他东西,或未定义的行为?标准容器在这里有任何定义的语义吗?

相关:这个线程讨论你是否应该关心自己的类中的自移动,但不讨论标准容器的移动赋值操作符是否这样做,并且不提供标准引用。

NB。这与w = static_cast< std::vector<int> && >(w);完全相同,还是std::move是一个函数的事实有所不同?

§17.6.4.9 [res.on.arguments]:

下列各项适用于c++标准库中定义的函数的所有实参,除非另有明确说明:

  • […]
  • 如果函数实参绑定到右值引用形参,则实现可以假定此形参是对该实参的唯一引用。[注:如果形参是T&&形式的泛型形参,并且绑定了A类型的左值,则实参绑定到左值引用(14.8.2.1),因此不包括在前面的句子中。]注:如果一个程序在将左值传递给库函数的同时将左值强制转换为xvalue(例如,通过调用带参数move(x)的函数),该程序实际上是在要求该函数将该左值视为临时值。该实现可以自由地优化掉在参数为左值时可能需要的混叠检查。

由于实现可能假设该形参是对该实参的唯一引用,而自移动赋值会违反此假设,因此它具有未定义行为。

参见LWG issue 1204