标准库对自动分配的保证是什么?

Bja*_*une 41 c++ stl move-semantics c++11

C++ 11标准对标准库相关的自移动赋值有何看法?更具体的是,什么(如果有的话)保证什么selfAssign呢?

template<class T>
std::vector<T> selfAssign(std::vector<T> v) {
  v = std::move(v);
  return v;
}
Run Code Online (Sandbox Code Playgroud)

How*_*ant 35

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

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

...

  • 如果函数参数绑定到右值引用参数,则实现可以假定此参数是对此参数的唯一引用.[注意:如果参数是T &&形式的通用参数并且绑定了类型A的左值,则参数绑定到左值引用(14.8.2.1),因此不包含在前一句中. - 结束注释] [注意:如果程序在将左值传递给库函数时将左值转换为x值(例如通过使用参数move(x)调用函数),程序实际上会要求该函数处理该左值作为临时的.实现可以自由地优化别名检查,如果参数是anlvalue则可能需要这些检查.-endnote]

因此,std::vector<T, A>::operator=(vector&& other)允许实现假设这other是一个prvalue.如果other是prvalue,那么自动移动分配是不可能的.

可能发生的事情:

v将保持无资源状态(0容量).如果v已经有0容量,那么这将是一个无操作.

更新

最新的工作草案,N4618已被修改,明确规定,在MoveAssignable规定的表达式:

t = rv
Run Code Online (Sandbox Code Playgroud)

(其中rv是rvalue),t只需rv要是赋值之前的等价值,如果t并且rv不引用同一个对象.无论如何,rv在任命之后,状态是未指定的.还有一个说明需要进一步说明:

rv还必须满足在使用它,无论是否在该库组件的要求t,并rv指向同一个对象.

  • 如果我正确理解你的引用,那么函数`selfAssign`会调用未定义的行为,因为不满足移动赋值运算符的前提条件.我的理解是`std :: swap`将在调用`std :: swap(v,v)`上进行自移动赋值.这是否使得调用`std :: swap(v,v)`的行为不明确? (5认同)
  • @MatthieuM.:这只是标准所说的*它自己的*功能; 这不是关于`&&`参数的一般陈述.在您编写的代码中,您不会受到限制. (2认同)

yep*_*ons 5

Eric Niebler发表了一篇相关帖子,其中包含多个链接,例如Howard Hinnant 的回答

\n

就我的口味而言,最新的 \xd0\xa1++20 工作草案(N4861)在这个问题上仍然有点模糊。然而,最近的图书馆工作组第 2839 期在 中添加了以下明确声明[lib.types.movedfrom]/2

\n
\n

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

\n
\n

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

\n

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

\n