C ++ 11标准对标准库中的自移动赋值有何看法?更具体一点是,selfAssign
做什么可以保证什么呢?
template<class T>
std::vector<T> selfAssign(std::vector<T> v) {
v = std::move(v);
return v;
}
答案 0 :(得分:33)
17.6.4.9函数参数[res.on.arguments]
1以下各项适用于定义的函数的所有参数 除非另有明确说明,否则在C ++标准库中。
...
- 如果函数参数绑定到右值引用参数,则实现可以假定此参数是对其的唯一引用 这个论点。 [注意:如果参数是通用参数 形式T&amp;&amp;并且绑定了一个类型A的左值,该参数绑定到一个 左值参考(14.8.2.1)因此不在前面 句子。 - 结束注释] [注意:如果程序将左值转换为 将左值传递给库函数时的xvalue(例如通过 用参数move(x)调用函数,程序是 有效地要求该函数将该左值作为临时值处理。 实现可以自由地优化别名检查 如果参数是anlvalue可能需要。 -endnote]
因此,允许std::vector<T, A>::operator=(vector&& other)
的实现假设other
是prvalue。如果other
是prvalue,则无法进行自动分配。
可能发生的事情:
v
将处于无资源状态(0容量)。如果v
已经有0容量,那么这将是一个无操作。
<强>更新强>
latest working draft, N4618已被修改,以明确说明MoveAssignable
要求中的表达式:
t = rv
(其中rv
是右值),如果t
和rv
没有t
,则rv
只需要在分配之前为rv
的等效值引用相同的对象。无论如何,rv
的状态在分配后未指定。还有一个说明需要进一步澄清:
无论t
和rv
是否引用相同的对象,{{1}}仍必须满足使用它的库组件的要求。
答案 1 :(得分:0)
a relevant post by Eric Niebler 有多个链接,例如到this answer by Howard Hinnant。
最新的 С++20 工作草案(N4861)在我看来仍然有些模棱两可。但是,最近有一个 Library Working Group issue 2839 在 [lib.types.movedfrom]/2
中添加了以下显式语句:
在 C++ 标准库中定义的类型的对象可以移动分配 (11.4.6 [class.copy.assign]) 给自身。除非另有说明,否则这种赋值会将对象置于有效但未指定的状态。
它已经在 C++23 的 N4885 工作草案中了。
因此,selfAssign
保证不会导致未定义的行为,并且由于 std::vector
没有额外的保证,因此将 v
保留在某个有效状态。