Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是->;为迭代器my_map.end()定义了第二个?_C++_Stl_Iterator - Fatal编程技术网

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:很高兴它对您有所帮助