std::vector::erase()和std::deque::erase()中的复制/移动赋值

140
在回答另一个问题的过程中,我发现了std :: vector :: erase()std :: deque :: erase()的略微不同措辞。
这是C ++14关于std :: deque :: erase [deque.modifiers] / 4-6 ,强调我自己)的说法:

效果: ...

复杂度:调用析构函数的次数与删除的元素数量相同,但赋值运算符的调用次数不超过被删除元素之前和被删除元素之后的元素数量中的较小者。

抛出:除非T的复制构造函数,移动构造函数,赋值运算符或移动赋值运算符抛出异常,否则不会抛出任何异常。

这是关于std :: vector :: erase [vector.modifiers] / 3-5 )的内容。

效果:...

复杂度:调用T的析构函数次数等于删除的元素数量,但是在删除元素之后,调用T移动赋值运算符的次数等于向量中元素的数量。

抛出异常:除非T的复制构造函数、移动构造函数、赋值运算符或移动赋值运算符抛出异常,否则不会抛出异常。

正如您所看到的,它们的异常规范是相同的,但是对于std::vector,明确提到了调用移动赋值运算符。

T对于erase()std::vectorstd::deque中都需要是MoveAssignable(表100),但这并不意味着必须存在移动赋值运算符:可以定义一个复制赋值运算符而不定义移动赋值运算符,这个类仍然是MoveAssignable

为了确保,我检查了GCC和Clang,的确std::vector::erase()在没有移动赋值运算符的情况下调用复制赋值运算符,而std::deque::erase()也是如此(DEMO)。

因此问题是:我有遗漏吗?还是这是标准中的(编辑)问题?

更新: 我已经提交了LWG issue #2477


14
标准似乎存在缺陷。 - Barry
4
明白了,这句话的意思是“可以考虑提出一个LWG问题来解决这个问题。” - Columbo
4
通常情况下,草案标准已经足够好了。但这是你需要查看实际内容的情况之一。 - Mark Ransom
3
@MarkRansom std::dequestd::vector的当前标准来源与问题所述相同,因此最终版本有所不同的可能性非常小。 - Anton Savin
3
N4141与N4140的措辞相同。 - Brian Bi
显示剩余4条评论
1个回答

10

在Lenexa会议上,提出的解决方案迅速得到了立即的关注

此措辞与N4296有关。

更改23.3.3.4 [deque.modifiers]/5为:

-5- 复杂度: 析构函数T的调用次数与擦除元素的数量相同,但T的赋值操作符的调用次数不超过擦除元素之前和之后的元素数量中较小的那个。

更改23.3.6.5 [vector.modifiers]/4为:

-4- 复杂度: 调用T的析构函数的次数等于所删除的元素的数量,但调用T移动赋值操作符的次数等于被删除元素之后的向量元素数量。

如果这项提案被接受,那么在std::vector::erase中将不会特别提到移动赋值,并且std::deque::erase的措辞也会得到一些澄清。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接