为什么' std::prev '不会用' std::unordered_set '的迭代器引发错误?
Why `std::prev` does not fire an error with an iterator of `std::unordered_set`?
我的问题与下面链接的问题有关。unordered_map?中的双向迭代器
由于我不知道std::unordered_set
不支持双向迭代器,我碰巧写了一段类似于下面的代码。
int main(){
unordered_set<int> y{4};
std::cout << *(std::prev(y.end())) << std::endl;
}
程序已编译,但最后一行代码使程序崩溃。对此感到困惑的是,我遇到了一个相关的问题。然而,我仍然不明白为什么这个程序被编译而不是抛出错误消息,而链接代码中的代码(这是boost::unordered_set
)无法编译。你能解释一下吗?
供参考,我使用Mingw64与g++ 4.8.2/Windows 7/64位环境。
std::prev
只产生双向迭代器的定义行为。
GNU ISO c++库(GCC 4.8.2使用)使用std::advance
来实现std::prev
, std::advance
本身是这样实现的:
-
用于随机访问迭代器:
__i += __n;
-
用于双向迭代器:
if (__n > 0) while (__n--) ++__i; else while (__n++) --__i;
-
用于所有其他迭代器:
while (__n--) ++__i;
因此,您可以看到,对于unordered_set
的迭代器,该函数实际上没有使用operator--
,从而在您链接的另一个问题中产生编译错误。
你有责任确保传递给std::prev
的迭代器是双向的。如果不是这样,c++标准就不能保证会发生什么。GCC选择静默地忽略它,但它也可能使程序崩溃。
std::prev
可能使用了std::advance
,其中,当参数(Input Iterator)不是双向时,行为是未定义的。
相关文章:
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 如何在c++迭代器类型中包装std::chrono
- std::vector::迭代器是否可以合法地作为指针
- 为什么 C++ std::unordered_map 从 emplace/ 找到返回一个迭代器?
- 如何在创建自定义迭代器时获得 std::p air 的第一个和第二个?
- 修改 std::vector 会使迭代器无效吗?
- std::list 中的迭代器感知对象
- 迭代器库中的 std::size() 不适用于传递给函数的 C 样式数组
- C++如何乘以包含 std::variant 元素的向量的迭代器?正在执行迭代器类型的转换?
- 为什么 std::迭代器被弃用?
- std::迭代器是否可以检查该迭代器上是否存在下一个元素?(此设计受到家庭作业的限制)
- std::迭代器到自身的映射
- std::迭代器的准备工作已弃用
- std::迭代器、指针和 VC++ 警告 C4996
- 指向指针的STD迭代器;为应该是等价的代码获取不同的类型
- C++ std::迭代器何时以及如何使用value_type、引用、指针
- C++ std::迭代器,内部不使用 std::vector 或 std::list
- 传递std::迭代器,指向具有特征类型的向量
- 在c++中通过std迭代器将基类强制转换为派生类