C++迭代器自减与减1操作的语义区别及不同容器适配性问题
迭代器获取末尾前一位的写法差异分析
第一种与第二种写法的核心语义差异
两种写法的本质区别在于对右值操作数的运算符兼容性要求不同,和STL的迭代器实现规则直接相关:
- 对于
--container.end():
C++标准允许std::vector的迭代器直接实现为原生指针(符合规范的合法实现)。而原生指针属于内建类型,自减运算符--要求操作数必须是可修改的左值。container.end()返回的是临时对象(右值),如果迭代器是原生指针,对右值指针执行--属于语法不合法,直接编译失败。
只有当vector迭代器被实现为自定义类类型时,类的成员函数operator--允许被右值对象调用,此时该写法才能正常运行,属于实现相关的不可移植写法。 - 对于
container.end() - 1:
减法运算符-对于内建指针类型本身支持右值操作数,不存在左值约束,因此哪怕迭代器是原生指针,右值减1也是合法语法。但该运算符仅随机访问迭代器支持,本身有容器类型限制。
不同容器类型的结论变化
写法的合法性和容器的迭代器类型直接绑定:
- 随机访问迭代器容器(vector、array、deque):
第二种写法仅在这类容器中合法,第一种写法依然存在原生指针实现下的编译失败问题,两种写法的可移植性都远低于第三种写法。 - 双向迭代器容器(list、set、map、multiset、multimap):
这类容器的迭代器不支持随机访问,没有实现operator-,第二种写法直接编译报错。第一种写法同样存在右值自减的实现依赖问题,只有std::prev(container.end())是标准规定的通用合法写法。 - 前向迭代器容器(forward_list等):
迭代器仅支持向前移动,三种写法均不合法,无法直接通过end()后退获取末尾元素。
注意:以上所有写法的前置条件是容器非空,若容器为空,对end()执行后退操作均属于未定义行为。
内容的提问来源于stack exchange,提问作者ByteEater
相关产品推荐
相关产品推荐

