std::vector<T>::iterator::operator[]是否为定义行为及相关疑问
std::vector<int> vec{0, 1, 2, 3, 4, 5, 6, 7}; std::cout << (vec.begin() + 4)[2] << " \n"; // 输出6 std::cout << (vec.begin() + 4)[-1] << "\n"; // 输出3
上述代码执行后能得到预期的6和3,但在cppreference上找不到std::vector::iterator::operator[]的定义,因此疑惑该行为是否属于C++标准定义的行为。
通过g++-11编译器的头文件(vector、bits/stl_vector.h及bits/stl_iterator.h)发现,迭代器的_M_current成员是T*类型,负数索引符合指针算术逻辑,但还有两个疑问:
- 随机访问迭代器是否必须模仿
T*的所有算术操作? T*::operator[]是否在C++中有定义?定义位置在哪?
1. 随机访问迭代器的operator[]是标准强制要求
C++标准里,**随机访问迭代器(RandomAccessIterator)**的概念明确规定了operator[]的行为:对于随机访问迭代器it和整数n,it[n]等价于*(it + n)。这是迭代器抽象的一部分,并非std::vector::iterator单独定义的,所以cppreference会把这部分内容放在随机访问迭代器的通用文档中,而非单独列在vector::iterator的条目下。
至于负数索引,只要it + n指向容器内的有效元素(或尾后位置),it[n]就是合法的。比如(vec.begin() + 4)[-1]等价于*(vec.begin() + 4 - 1),也就是*(vec.begin() + 3),对应元素3,完全符合标准规定。
2. 指针的operator[]是C++核心语言定义的
T*的operator[]属于C核心语言特性,不是某个标准库提供的。标准明确规定:对于指针p和整数n,p[n]等价于*(p + n),这里的n可以是负数,只要p + n指向有效的对象(比如数组范围内的元素)。这个规则在C标准的表达式章节中关于指针算术和下标运算符的部分有明确说明。
3. 随机访问迭代器与指针的关系
随机访问迭代器不需要完全复刻指针的所有操作,但必须满足标准规定的随机访问迭代器概念的全部要求,其中就包括operator[]、加减运算、比较运算等。std::vector的迭代器通常是原生指针的封装(甚至直接就是原生指针),所以行为和指针一致,但这是实现细节,标准只要求它符合随机访问迭代器的接口和行为规范。
内容的提问来源于stack exchange,提问作者gxu

