2. 解引用和指针算术操作之间的相互作用
int i[]= {1, 2, 3};
int *j = i;
cout << *(j+2) << endl;
3. 下标和指针
在表达式中使用数组名时,实际上使用的是指向数组第一个元素的指针。
使用下标访问数组时,实际上是使用下标访问指针。
int i[]= {1, 2, 3, 4, 5};
int *j = &i[1];
cout << j[2] << endl; //4
4. 计算数组的超出末端指针
vector类型提供的end操作将返回指向超出vector末端位置的一个迭代器。这个迭代器常用作哨兵,来控制处理vector中元素的循环。类似地,可以计算数组的超出末端指针的值。
const int arry_size = 5;
int i[]= {1, 2, 3, 4, 5};
int *j = &i[0];
int *k = j + arry_size;
C++允许计算数组或对象的超出末端的地址,但不允许对此地址进行解引用操作。而计算数组超出末端位置之后或数组首地址之前的地址都是不合法的。
5. 输出数组元素
const int arry_size = 5;
int arr[arry_size]= {1, 2, 3, 4, 5};
for(int *i=arr, *end = arr+ arry_size; i!=end; i++)
{
cout << *i << endl;
}
6. 指针是数组的迭代器
4.2.5 指针和const限定符
1. 指向const对象的指针
C++语言强制要求指向const对象的指针也必须具有const特性。
const int arry_size = 5;
const int* i = &arry_size;
cout << *i << endl;
const限定了指向const的指针所指向的对象类型,而非指向const的指针本身。也就是说,指向const的指针本身不是const。在定义时不需要对它进行初始化,如果需要的话,允许给指向const的指针重新赋值,使其指向另一个const对象。但不能通过指向const的指针修改其所指对象的值。
const int arry_size = 5;
const int* i;
i = &arry_size;
cout << *i << endl;
不能使用void*指针保存const对象的地址,而必须使用const void*类型的指针保存const对象的地址。
允许把非const对象的地址赋给指向const对象的指针。
int i = 5;
int *p = &i;
const int *p2 = p;
cout << *p2 << endl;
指向const的指针一经定义,就不允许修改其所指对象的值,如果该指针恰好指向非const对象时,同样不允许通过其修改对象值。
不能使用指向const对象的指针修改基础对象,然而如果该指针指向的是一个非const对象,可以用其他方法修改其所指的对象。
可以修改指向const的'指针所指向的值。(间接地)
int i = 5;
int *p = &i;
const int *p2 = &i;
*p = 4;
cout << *p2 << endl;
如果指向const的指针的对象并非const,则可直接给该对象赋值或间接地利用普通的非const指针修改其值:毕竟这个值不是const。重要的要记住:不能保证指向const的指针所指对象的值一定不可修改。
把指向const的指针可以理解为"自以为指向const的指针"。
在实际的程序中,指向const的指针常用做函数的形参。将形参定义为指向const的指针,以此确保传递给函数的实际对象在函数中不因为形参而被修改。