50

C++11 标准对与标准库相关的自移动赋值有什么看法?更具体地说,什么,如果有的话,保证什么selfAssign

template<class T>
std::vector<T> selfAssign(std::vector<T> v) {
  v = std::move(v);
  return v;
}
4

2 回答 2

40

17.6.4.9 函数参数 [res.on.arguments]

1 除非另有明确说明,否则以下各项均适用于 C++ 标准库中定义的函数的所有参数。

...

  • 如果函数参数绑定到右值引用参数,则实现可能假定此参数是对该参数的唯一引用。[ 注意:如果参数是 T&& 形式的泛型参数并且绑定了类型 A 的左值,则参数绑定到左值引用 (14.8.2.1),因此上一句未涵盖。— end note ] [ 注意:如果程序将左值转换为 xvalue,同时将该左值传递给库函数(例如,通过使用参数 move(x) 调用函数),则程序实际上是在要求该函数处理该左值作为临时。如果参数是左值,则该实现可以免费优化别名检查,这可能需要。——尾注]

因此,std::vector<T, A>::operator=(vector&& other)允许的实现假定它other是一个prvalue。如果other是纯右值,则无法进行自移动分配。

可能发生的情况:

v将处于无资源状态(0 容量)。如果v已经有 0 容量,那么这将是一个空操作。

更新

最新的工作草案 N4618已被修改为在要求中明确说明MoveAssignable

t = rv

(其中rv是一个右值),如果并且不引用同一个对象,则只需是赋值之前t的等效值。无论如何,分配后的状态是未指定的。有一个附加说明需要进一步说明:rvtrvrv

rv必须仍然满足使用它的库组件的要求,无论是否引用同一个对象trv

于 2012-10-29T18:55:59.147 回答
0

Eric Niebler有一个相关的帖子,其中包含多个链接,例如Howard Hinnant 的这个答案

最新的С++20工作草案(N4861)在我看来仍然有点模棱两可。但是,最近有一个图书馆工作组问题 2839,它在以下位置添加了以下明确声明[lib.types.movedfrom]/2

C++ 标准库中定义的类型的对象可以移动分配(11.4.6 [class.copy.assign])给它自己。除非另有说明,否则此类分配会将对象置于有效但未指定的状态。

它已经在 C++23 的 N4885 工作草案中。

因此,selfAssign保证不会导致未定义的行为,并且由于没有额外的保证std::vector,因此保持v在某些有效状态。

于 2021-04-05T11:50:38.560 回答