目摘要一正确迭代器二错误迭代器三现象的分析四错误的原因1语法理解2设计理解摘要我们在初学迭代器的时候常常这样一个疑问既然已经有了iterator为什么const修饰的迭代器不是const iterator而是一个新的类型const_iterator这篇文章旨在解决这个疑惑....一正确迭代器以下是不同类型迭代器的正确书写方式(假设类型为 int)//正常迭代器 typedef int* iterator; //const迭代器 typedef const int* const_iterator;正常迭代器效int main() { int arr[] { 1, 2, 3, 4, 5 }; typedef int* iterator; iterator it arr; *it 10;//it指向的内容可以更改 it;//it本身也可以更改 std::cout val: *it std::endl; return 0; }解释正常迭代器 it本身可修改*it指向的内容也可以修改const迭代器的效果int main() { int arr[] { 1, 2, 3, 4, 5 }; typedef const int* const_iterator; const_iterator c_it arr; // c_it 是 const int* //*c_it 30; // 非法 c_it; // 合法 std::cout const_iterator: *c_it std::endl; return 0; }解释const迭代器 it本身可修改 但it指向的内容不可以修改 若将代码中的//*c_it 30;的注释去掉 则会报错 这符合const迭代器的行为二错误迭代器其实我们的疑问“既然已经有了iterator为什么const修饰的迭代器不是const iterator而是一个新的类型const_iterator”完全可以转换为这个问题为什么const iterator不等价与const_iterator在上文中我知道//正常迭代器 typedef int* iterator; //const迭代器 typedef const int* const_iterator;那为什么不能写作//正常迭代器 typedef int* iterator; //const迭代器 const iterator在我们看来正确写法中const_iterator是const int*的别名那为什么不能直接对是int*别名的iterator前加一个const形成 const iterator这不也是const int*吗下面就测试若是用const iterator 替代 const_iterator会有什么效果?int main() { int arr[] { 1, 2, 3, 4, 5 }; typedef int* iterator; iterator it arr; *it 10;//it指向的内容可以更改 it;//it本身也可以更改 std::cout val: *it std::endl; //用const iterator来替代const_iterator const iterator cit arr; *cit 20; // 合法 // cit; // 非法 std::cout const iterator: *cit std::endl; return 0; }解释发现const iterator效果和 const_iterator 刚好相反const_iteratorcit本身可以改变 但不能改变cit指向的内容const iterator cit本身不能改变 但可以改变cit指向的内容首先不管为什么相反只要没达到cit本身可以改变*cit不能改就代表我们想法是错的❓️为什么const iterator这种写法和真正的const_iterator天差地别在我们看来所以对于两个框来说应该都是一样iterator it创建出的it就是int*类型变量所以it可以*it也可以const_iterator cit和 congst iterator cit二者创建出的cit都是const int*类型的变量所以cit可以*cit不能修改但是const iterator cit出的cit是*cit可以修改而cit本身不可以修改三现象的分析那错误的原因是什么*cit可以修改而cit本身不可以修改其实从这个现象我们就可以分析出const到底在修饰哪部分了cit的类型一定是 int* constconst修饰的是cit指针所以cit指针不可以修改而*cit可以修改所以cit的类型为int* const创建语句为 int* const citconst的修饰规则语法写法const 修饰对象能否修改指向的内容能否修改指针本身说明const int* a指针所指向的对象int❌ 不能✅ 能const 在*左边修饰指向的内容int const* a指针所指向的对象int❌ 不能✅ 能与上一行完全等价const 在*左边int* const a指针本身*✅ 能❌ 不能const 在*右边修饰指针本身const int* const a指向的对象int 指针本身*❌ 不能❌ 不能两个 const 分别修饰内容和指针四错误的原因1语法理解//正常迭代器 typedef int* iterator; //const迭代器 const iterator所以错误的原因就在于const iterator不是直接把iterator替换为int*从而变成const int*换句话说我们需要理解类型别名typedef在const修饰时的整体性实际的替换正确因为const iterator 的时候const 修饰的是 iterator 这个类型的别名此时的iterator 是一个整体 所以其实替换之后是const (int*)const修饰的是(int*)这个整体而int*是什么这很明显是一个指针类型所以const修饰的是指针类型所以指针不能修改而指针指向的内容可以修饰这也是为什么错误的citcit不能反而*cit可以修改的原因本质就是因为const (int*) 和 const int *是两回事前者修饰(int*)这个整体后者修饰的是int所以前者指针不能修改后者指针指向的int类型的内容不能修改2设计理解除了语法上的理解我们还能通过设计来理解const iterator的错误原因首先我们知道迭代器不是真正的指针而是模仿指针的行为那为什么不是指针却可以*it达到解引用的效果呢很简单因为iterator是一个类其对*操作符进行重载使其达到了解引用的效果所以迭代器不是原生指针而是封装了指针的类解引用*it实际调用的是operator*()重载函数const iterator it表示it是一个iterator类型的const对象。这意味着it本身不可变不能执行it或it other等修改自身指向的操作但*it能否修改并不由it的const属性决定而由iterator类中operator*()的返回类型决定。在标准库设计中iterator的operator*() const返回的是普通引用T因为修改指向的内容不影响迭代器对象自身的成员变量因此const iterator表现类似于T* const指针本身锁定但指向的内容可写。所以const iterator it const修饰的是对象而要像让const真正的修饰到对象中的成员变量指针指向的资源我们是无法通过const和iterator来做到的必须重新起一个叫做const_iterator的类而const_iterator则是一个独立类型其内部存储的是const T*指针且operator*()统一返回const T。无论该类型的对象本身是否为const通过它解引用得到的结果都是只读的因此*it不可修改但it本身可以递增或赋值。若要同时禁止修改迭代器和禁止修改指向内容则需声明const const_iterator it此时两者均被锁定。综上const iterator与const_iterator服务于不同的语义需求前者锁定迭代器本身后者锁定迭代器指向的资源。两者不可混用也无法通过单纯给iterator加const来达到const_iterator的效果因为const修饰对象时仅约束其成员变量本身而无法穿透到成员指针所指向的资源。这正是C中“顶层const”与“底层const”在设计层面的体现也是迭代器体系精妙之处。// iterator it 中的*i调用的函数 T operator*() { return *ptr; } //const_iterator it调用的函数 const T operator*() const { return *ptr; } // const iterator it 中的*it调用 // const 对象调用也返回普通引用因为修改 *it 不影响对象成员变量本身 T operator*() const { return *ptr; } [ 作者 ] shylyly [ 首次发布 ] 2025.3.7❌ [ 最新修改 ] 2026.8.2 [ 声明 ] 由于笔者水平有限文中难免有疏漏或不妥之处还望读者不吝教