一:正确书写迭代器的效果
在我们模拟实现一个类的时候,常常会自己模拟实现一个迭代器,实现迭代器的时候,常常会有这么一个疑问,为什么不能用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迭代器的行为
二:用const iterator 替代 const_iterator的效果
那若是用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_iterator:it本身可以改变 但不能改变it指向的内容
const iterator: it本身不能改变 但可以改变it指向的内容
很显然,const iterator这种写法,和真正的const_iterator天差地别,那这是为什么呢?
三:const的修饰规则
①:const
修饰规则
在 C++ 中,const
的修饰规则如下:
const
修饰的是它左边的内容(如果没有左边的内容,则修饰右边的内容)。
②:用几种例子来体现const的修饰规则
情况 1:const int* a
语法:const int* a;
const
修饰的是 int
,即指针 a
所指向的对象是常量。(左边没有内容,则修饰右边的内容)
示例:
const int* a = &x;
// *a = 10; // 错误:不能通过 a 修改所指向的对象
a = &y; // 正确:a 本身可以修改,指向 y
情况 2:int const* a
语法:int const* a;
含义:与 const int* a
完全相同。
const
修饰的是 int
,即指针 a
所指向的对象是常量。(左边有内容,则修饰左边的内容)
示例:
int const* a = &x;
// *a = 10; // 错误:不能通过 a 修改所指向的对象
a = &y; // 正确:a 本身可以修改,指向 y
情况 3:int* const a
语法:int* const a;
含义:a
是一个常量指针,指向 int
类型的对象。
const
修饰的是 *
,即指针 a
本身是常量。(左边有内容,则修饰左边的内容)
示例:
int* const a = &x;
*a = 10; // 正确:可以通过 a 修改所指向的对象
// a = &y; // 错误:a 是常量指针,不能改变指向
情况 4:const int* const a
语法:const int* const a;
含义:a
是一个常量指针,指向 const int
类型的对象。
第一个 const
修饰的是 int
,即指针 a
所指向的对象是常量。
第二个 const
修饰的是 *
,即指针 a
本身是常量。
示例:
const int* const a = &x;
// *a = 10; // 错误:不能通过 a 修改所指向的对象
// a = &y; // 错误:a 是常量指针,不能改变指向
总结:
const
的位置决定了它修饰的对象:
如果 const
在 *
的左边(如 const int*
或 int const*
),它修饰的是指针所指向的对象。
如果 const
在 *
的右边(如 int* const
),它修饰的是指针本身。
四:const iterator 不能替代 const_iterator的原因
所以:
const iterator c_it = arr 意思是尽管这里的iterato是int * 但是不能直接替换进去变成:
const int * cit = arr
原因:
因为const iterator 的时候,const 修饰的是 iterator 这个类型的别名,此时的iterator 是一个整体 ,内容为int *,既然要修饰int *, 再结合我们的修饰规则,所以此时的const应该放在int*的右边
替换后的效果:int * cosnt c_it = arr;
而真正的const_iterator的效果:csont int * c_it = arr;
所以,看似直接替换进去是一样的,但是因为有const的修饰规则,所以并没有真正的直接原封不动的替换进去