删除映射和分割错误中的一个过去结束元素

deletion of one past end element in map and segmentation fault

本文关键字:一个 过去 元素 结束 映射 分割 错误 删除      更新时间:2023-10-16

当我尝试使用erasemap中删除end()元素时,我在编译中没有遇到任何问题,但是在后来打印map.begin()键/mapped_value时,我遇到了分段错误:

//RELEVANT HEADERS
//main function starts
map<int, string> m;
m[0] = "hello";
m[1] = "Mello";
m.erase(m.end());
cout<<(m.begin())->second;

输出:Segmentation fault

我的问题是:在尝试删除end()元素时,映射m的结构不会发生任何事情,因为end指的是一个经过真正的结束元素,所以真正触发该segmentation fault的是什么,因为内存结构仍然与删除前相同。

正如你在cppreference关于std::map::erase的文档中看到的那样,传递给它的迭代器必须是调用erase的容器的有效迭代器,并且它必须是可取消引用的。

迭代器end()不可取消引用。因此,将其传递给erase违反了erase的前提条件,这意味着您的程序具有未定义的行为

未定义的行为意味着无法保证程序将做什么(或它是否会编译(,因此它完全有可能一直工作到程序的稍后某个地方和/或您遇到分段错误。这些是未定义行为的可能表现。


实际上,erase调用可能会取消引用迭代器中包含的某个指针,该指针不指向任何元素并触发分段错误。但这是一个依赖于标准库实现的实现细节,无论如何都无关紧要,因为规则是由语言给出的,上面描述了。

std::map::erase()可以采用以下三种类型的参数之一:

  • 迭 代
  • 迭代器范围
  • 键值

您正在传递一个迭代器,但它是end(),它比映射中的最后一个元素过去一个。根据 cpp 对std::map:erase()的偏好:

迭代器 pos 必须有效且可取消引用。因此结束(( 不能使用迭代器(有效,但不可取消引用( 作为 POS 的值。

因此,要使std::map::erase()使用迭代器,指向的元素必须是映射中的有效元素。否则,所有的赌注都会关闭,你可能会得到不确定的行为