如果传递空范围,vector::erase() 返回什么迭代器?

Bor*_*ein 8 c++ vector stdvector

根据cppreference.comcplusplus.com,该函数std::erase(first, last)返回“最后一个删除元素之后的迭代器”。

但是,在完全没有被移除元素的特殊情况下,即当first == last(空范围)时,返回值是什么不清楚。截至 2020 年 1 月 19 日,上述消息来源均未提及此特殊情况。

例如,在以下代码中:

std::vector<int> v{1, 2, 3, 4};
auto it1 = v.erase(v.begin(), v.begin());
auto it2 = v.erase(v.end(), v.end());
Run Code Online (Sandbox Code Playgroud)

it1和的值是it2什么?

Bor*_*ein 10

这在[sequence.reqmts] 中指定:

返回的迭代器a.erase(q1, q2)指向q2在任何元素被擦除之前指向的元素。如果不存在这样的元素,a.end()则返回。

(注意:我链接了 C++17 最终工作草案,但这种措辞至少从 C++98 开始就存在,请参阅@Peter 的评论)

所以我们应该有it1 == v.begin()it2 == v.end()

现场测试

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v{1, 2, 3, 4};
    auto it1 = v.erase(v.begin(), v.begin());
    auto it2 = v.erase(v.end(), v.end());
    std::cout << std::distance(v.begin(), it1) << std::endl;
    std::cout << std::distance(v.begin(), it2) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

输出:

0
4
Run Code Online (Sandbox Code Playgroud)

为了澄清这种行为,我更新了cppreference文档,现在是:

iterator erase( const_iterator pos );
iterator erase( const_iterator first, const_iterator last );
Run Code Online (Sandbox Code Playgroud)

返回值

最后一个删除元素之后的迭代器。

如果 pos 指向最后一个元素,则返回 end() 迭代器。

如果 last==end() 在移除之前,则返回更新的 end() 迭代器。

如果 [first, last) 是空范围,则返回 last。

  • 这并非特定于 C++17 最终工作草案。第一个 C++ 标准中也有相同的措辞(ISO/IEC 14882,第一版 1998-09-01,第 23.1.1 节 [lib.sequence.reqmts],第 8 段)。前面的第 7 段对 `erase` 的单参数形式做出了类似的陈述 - “从 `a.erase(q)` 返回的迭代器指向紧接在 `q` 之后的元素被删除之前的元素。如果没有这样的元素存在,返回`a.end()`。” (3认同)