VS2019 Release模式下std::map右值插入结果检查异常原因咨询
VS2019 Release模式下std::map迭代器比较异常问题分析
问题现象
原始测试代码
typedef std::map<int, double> M; typedef M::value_type VT; const VT v0; M mm; CHECK(mm.begin() == mm.insert(v0).first);
执行结果(仅VS2019 Release模式,C++17及以上版本):
ERROR: check is NOT correct CHECK( mm.begin() == mm.insert(v0).first )
values: CHECK( {?} == {?} )
四种修改写法仍失败
尝试以下四种调整写法,结果依旧为false:
- 显式转换为bool:
CHECK(bool(mm.begin() == mm.insert(v0).first));
- 调换比较顺序并显式转换:
CHECK(bool(mm.insert(v0).first == mm.begin()));
- 直接调换比较顺序:
CHECK(mm.insert(v0).first == mm.begin());
- 先赋值给bool变量再检查:
const bool result = mm.insert(v0).first == mm.begin(); CHECK(result);
保存临时变量后成功
将insert返回的迭代器保存到临时变量后,检查正常通过:
typedef std::map<int, double> M; typedef M::value_type VT; const VT v0; M mm; M::iterator it = mm.insert(v0).first; CHECK(mm.begin() == it);
执行结果:
SUCCESS: check is correct CHECK( mm.begin() == it )
values: CHECK( {?} == {?} )
结论:这是VS2019的编译器Bug
该现象属于VS2019 Release模式下的编译器实现缺陷,而非C++标准允许的正常行为,核心依据如下:
- 迭代器有效性符合标准:根据C++标准
[map.modifiers]条款,std::map的插入操作不会使任何容器迭代器失效。因此mm.begin()和mm.insert(v0).first指向的是同一个元素,比较结果必然为true,与调用顺序无关。 - 临时迭代器生命周期被正确延长:C++标准规定,当临时对象绑定到
const左值引用时,其生命周期会延长至该引用所在的完整表达式结束。operator==(const std::map::iterator&, const std::map::iterator&)的参数是const引用,因此insert返回的临时迭代器的生命周期应覆盖整个比较表达式,比较操作是定义良好的。 - C++版本规则一致:C17在临时对象生命周期延长、map迭代器有效性的规则上,与C11、C++03完全一致,不存在版本差异导致的行为变化。
VS2019 Release模式的优化逻辑可能错误地提前销毁了临时迭代器,或在迭代器比较的实现上存在缺陷,导致直接比较时结果异常;而将迭代器保存到临时变量时,其生命周期被明确维持,因此比较结果正确。
内容的提问来源于stack exchange,提问作者Alexander G.
相关产品推荐
相关产品推荐

