C++ 是->;为迭代器my_map.end()定义了第二个?
我正在使用一个C++ 是->;为迭代器my_map.end()定义了第二个?,c++,stl,iterator,C++,Stl,Iterator,我正在使用一个std::map 我想测试my_map.find(key)是否返回了特定的指针 现在我正在做 auto iter = my_map.find(key); if ((iter != my_map.end()) && (iter->second == expected)) { // Something wonderful has happened } 但是,需要迭代器的运算符*来返回引用。直觉上我假设它是有效的并且完全初始化的?如果是这样,my_map.
std::map
我想测试my_map.find(key)
是否返回了特定的指针
现在我正在做
auto iter = my_map.find(key);
if ((iter != my_map.end()) && (iter->second == expected)) {
// Something wonderful has happened
}
但是,需要迭代器的运算符*
来返回引用。直觉上我假设它是有效的并且完全初始化的?如果是这样,my_map.end()->second
将是NULL
,并且(因为NULL
从来都不是预期的),我可以将If语句减少为:
if (iter->second == expected)
根据规格,这有效吗?有没有人在实现这一点上有实际经验?总之,代码变得更清晰了,而且可能会实现一个微小的性能改进
但是,需要迭代器的运算符*来返回引用。直觉上我假设它是有效的并且完全初始化的
您的假设是错误的,取消对迭代器的引用,即容器外的点将导致UB
24.2迭代器要求[迭代器要求]
24.2.1概述[迭代器.要求.概述]
7大多数在数据结构上运行的库算法模板都有使用范围的接口。
范围是一对迭代器,用于指定计算的开始和结束。范围[i,i]是一个
空范围;通常,范围[i,j]指数据结构中以元素开头的元素
由i指向,但不包括由j指向的元素。范围[i,j]在且仅当
j可从i访问。库中函数应用到无效范围的结果未定义。
直觉上我假设它是有效的并且完全初始化的
您不能假定容器末尾的元素的迭代器是可取消引用的。根据C++11标准第24.2.1/5段:
正如指向数组的常规指针保证有一个指针值指向最后一个元素一样
因此对于任何迭代器类型,都有一个迭代器值指向数组的最后一个元素
对应的序列。这些值在结束值之后调用。迭代器i
的值
定义的表达式*i
称为可取消引用的表达式。库从不假定超过的结束值是可取消引用的
可取消引用。[…]
如果
iter==my_map.end()
,则取消对它的引用是未定义的行为;但您在这里没有这样做
auto iter = my_map.find(key);
if ((iter != my_map.end()) && (iter->second == expected)) {
// Something wonderful has happened
}
如果iter!=my_map.end()
为false,则表达式的后半部分(iter->second==expected
)将不会执行
阅读“短路评估”。
指针的类似有效代码:
if ( p != NULL && *p == 4 ) {}
即使不检查规范,您也可以很容易地看到,在
末尾取消对迭代器的引用必须是无效的
一个非常自然的实现(vector
的de-factor标准实现)是end()
实际上是一个内存指针,其值为ptr\u last\u element+1
,即,如果存在下一个元素,则指针值将指向下一个元素
您不可能被允许取消引用end
迭代器,因为它可能是指向堆中下一个对象的指针,也可能是指向溢出保护区的指针(因此您可以取消引用随机内存),或者超过堆的末尾,并且可能超出进程的内存空间,在这种情况下,在取消引用时可能会出现访问冲突异常)。谢谢。非常有用,看到迭代器指针模拟确实有助于理解这个概念。@Rawler:很高兴它对您有所帮助