在 std::vector::erase() 和 std::d eque::erase() 中复制/移动赋值

Copy/move assignment in std::vector::erase() and std::deque::erase()

本文关键字:erase std 复制 移动 赋值 vector eque      更新时间:2023-10-16

在回答另一个问题的过程中,我偶然发现了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,明确提到调用移动分配运算符。

还需要MoveAssignable T,以便erase()同时使用 std::vectorstd::deque(表 100),但这并不意味着存在移动分配运算符:可以定义复制赋值运算符,而不定义移动赋值运算符,此类将被MoveAssignable

以防万一,我检查了 GCC 和 Clang,如果没有移动分配运算符,确实std::vector::erase()调用复制分配运算符,std::deque::erase()也这样做 (DEMO)。

所以问题是:我错过了什么,还是这是标准中的(编辑)问题?

更新:我已经提交了 LWG 问题 #2477。

在Lenexa会议上,该问题获得了建议解决方案的即时状态:

此措辞与 N4296 有关。

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

-5- 复杂性:对 T构函数的调用次数与擦除的元素数相同,但对 T值运算符的调用次数不超过被擦除元素之前的元素数和被擦除元素之后的元素数中的较小者。

将 23.3.6.5 [矢量修饰符]/4 更改为:

-4- 复杂性T 的析构函数称为等于擦除元素数的次数,但 T移动赋值运算符称为等于擦除元素后向量中元素数的次数。

也就是说,如果决议被接受,则不会特别提及std::vector::erase的移动分配,并且std::deque::erase的措辞将是澄清了一下。