0

假设我们有这段代码:

set<int> s;
set<int>::iterator it = s.find(val);
s.erase(it);

正如 cplusplus.com 所说,如果在thenint val中不存在,将返回.set<int> ss.find(val)set::end

现在我的问题是,如果我们传递set::endset::erase()?

是否可以接收诸如segmentation faultor之类的信号aborted并得到运行时错误?还是这个特殊情况被处理了set

4

3 回答 3

4

这是未定义的行为。即它可能什么都不做,使程序崩溃等。不要这样做,即使您的stdlib 实现“工作正常”。

于 2013-03-11T19:57:28.090 回答
4

在 C++03 中std::set::erase(),采用单个迭代器的 的行为在表 69 中定义,其中具有以下假设(添加了突出显示):

在表 69 中,X 是关联容器类,a 是 X 的值,a_uniq 是 X 支持唯一键时的值,a_eq 是 X 的值,当 X 支持多个键时,i 和 j 满足输入迭代器要求并引用 value_type 的元素,[i, j) 是有效范围,p 是 a 的有效迭代器,q 是 a 的有效可解引用迭代器,[q1,q2) 是 a 中的有效范围,t 是值X::value_type 的值,k 是 X::key_type 的值,c 是 X::key_compare 类型的值。

表 69 对此erase()函数进行了说明:

a.erase(q)- 擦除指向的元素q

换句话说,迭代器必须是可解引用的。如果不是,则它是未定义的行为,因为未满足前提条件。

没有关于图书馆以任何特定方式行事的承诺。某些库(例如 MSVC)可以在某些配置中包含迭代器调试。例如,在带有调试配置的 VS 2012 中运行时,您将看到以下内容:

---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
Debug Assertion Failed!

Program: C:\Windows\system32\MSVCP110D.dll
File: c:\program files (x86)\microsoft visual studio 11.0\vc\include\xtree
Line: 1326

Expression: map/set erase iterator outside range

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)

---------------------------
Abort   Retry   Ignore   
---------------------------
于 2013-03-11T20:00:16.267 回答
2

对于关联容器,erase定义如下:

a.erase(q)
返回类型:iterator
擦除 指向的元素q。返回一个迭代器,该迭代器指向紧跟q在被擦除元素之前的元素。如果不存在这样的元素,则返回a.end()

此函数仅根据 定义qq被描述为“一个有效的可取消引用的 const 迭代器a”。过去的迭代器是不可取消引用的,所以你会得到未定义的行为。

是否有可能接收到诸如分段错误或中止之类的信号并获得运行时错误?

是的,这是可能的,但你根本无法保证会发生什么。

于 2013-03-11T19:58:43.950 回答