指针部分:
指针是有固定类型的,但是C++提供了一种特殊的指针类型void*:
例如:
int val=1024;
void *pd=&val;//合法,void*可保存任何类型对象的地址
但是void*用法只支持比较,传递,返回和给另一个void*指针赋值
不允许使用void*操纵它所指向的对象
指针与引用的区别:
引用必须初始化,引用一经初始化就始终指向同一个特定对象,指针则可以随时指向其他对象。
例如:
将一个指针赋值给另一个指针:
int ival=1024,ival2=2048;
int *pi=&ival,*pi2=&ival2;
pi=pi2;
赋值结束后,pi指向的ival保持不变,赋值修改的是pi指针,使其指向不同对象
引用则不同
例如:
int &ri=ival,&ri2=ival2;
ri=ri2;
这个赋值修改了ri引用的ival对象,并非引用本身,赋值后,两个引用都还分别指向各自对象,此时ival=ival2=2048.
超出末端指针:
如同vector提供的end()操作一样,数组也允许存在一个超出末端指针作为哨兵,控制循环。
例如:
const int size=5;
int arr[size]={1,2,3,4,5};
int *p=arr;
int *p2=p+size;
此例p指向数组第一个元素,从0开始p+5即指向数组超出末端的位置,实际上不存在元素。
const指针和指向const对象的指针:
类似const类型迭代器和const_iterator一样:
指向const对象的指针:
const double *p;这里p本身不是const类型,定义时不必初始化,他是一个指向double类型const对象的指针。
也就是说*p=42这种操作是不允许的,不能企图通过指针修改值。但是可以改变指针的指向
例如:int s=3.14; p=&s;
const指针:
int s=0;
int *const cur=&s;
即指针本身的值不能修改
例如:
int *p;
cur=p;//不合法,本人认为这种不能移动的指针用处较少
还有一种指向const对象的const指针,显而易见是两种的结合。既不能修改所指对象值,也不能移动指针。
指针和typedef:
typedef string *pstring;
const pstring cstr;
cstr的真正意义与直观看相反,等价于:string *const cstr.,即一个不可改变指向的指针。
指针数组:
下题为读入多个字符串到vector,再定义指针数组,为每个字符串定义指针,最后输出。
下实例(*iter).c_str()是指一个string字符串转化为C规范的字符数组标准
int main()
{
string str;
vector<string> svec;
while (cin>>str)
{
svec.push_back(str);
}
char **parr=new char*[svec.size()];//定义一个指针数组
int ix=0,j=0;
for (vector<string>::iterator iter=svec.begin();
iter!=svec.end();++iter,++ix)
{
char *p=new char[(*iter).size()+1];//为每一个string开辟空间
strcpy(p,(*iter).c_str());//写入字符串到p
parr[ix]=p;//将指针放入指针数组
}
for (ix=0;ix!=svec.size();ix++,j++)
{
cout<<parr[ix]<<endl;
delete [] parr[ix];
}
delete [] parr;
return 0;
}
指针和多维数组:
多维数组的名字(ai)也是一个指针,只不过是一个指针数组。定义应用如下
int ai[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};
int (*p)[4]=ai;
for (;p!=ai+3;p++)//p是外围指针
{
for (int *q=*p;q!=*p+4;++q)//*p即解引用,内层指针
{
cout<<*q<<endl;
}
}