C++ Primer 学习笔记_Chapter4 数组和指针–指针
一、什么是指针?
指针与迭代器一样,指针提供对其所指对象的间接访问,指针保存的是另一个对象的地址;
string s("hello");
string *ps = &s; //ps holds the address of s
二、指针的定义和初始化
1、两种声明指针变量的风格
string *ps1;
string* ps2;
理解指针声明语句时,请从右向左阅读:
从右向左阅读pstring变量的定义,可以看到:
string *pstring;
语句把pstring定义为一个指向string类型对象的指针变量。
2、避免使用未初始化的指针
int *pi; //ok, but dangerous,pi is uninitialized
三、指针初始化和赋值操作的约束
对指针进行初始化和赋值只能使用以下四种类型的值:
1. 0值常量表达式;
2. 类型匹配的对象的地址;
3. 另一对象之后的下一地址;
4. 同类型的另一个有效指针。
四、void* 类型的指针
void* 类型的指针可以保存任何类型对象的地址。
double obj = 3.14;
double *pd = &obj;
void* pv = &obj;
pv = pd;
五、指针操作
1、生成左值的解引用操作
(1)解引用操作符返回指定对象的左值,利用这个功能可修改指针所指对象的值;
(2)修改指针本身的值,使sp指向另一个新的对象;
string s2 = "some new value";
sp = &s2;
2、指针和引用的比较
指针的和引用的相同点:
两者都可以间接访问另一个值;
指针和引用的重要区别:
(1)引用一经初始化,就始终指向某个特定对象,所以引用必须在定义时初始化;
(2)赋值行为的差异:给引用赋值修改的是该引用所关联的对象的值,而并不是使引用与另一个对象关联。引用相当于起别名。
3、使用指针访问数组元素
4、指针和const限定符
【指向const对象的指针】
【const指针】
1)指向const对象的指针
定义方式:
const double *cptr;
这里cptr是一个指向double类型const对象的指针,const限定了cptr所指向的对象类型,而并非cptr本身。也就是说cptr本身并不是const,所以,cptr在定义时,并不一定需要初始化。
【Warning】:
1、C++语言强制要求指向const对象的指针也必须具有const特性;
2、不能通过cptr修改所指对象的值;
*cptr = 42; //Error
3、把一个const对象的地址赋给一个指向普通的、非const对象的指针也会导致编译时的错误;
const double pi = 3.141592653589793 ;
double *pd = π //Error
const double *cptr = π //OK, cptr is a pointer to const
4、不能使用void*指针保存const对象的地址,而必须使用const void*类型的指针保存const对象的地址;
5、允许把非const对象的地址赋值给指向const对象的指针
double dval = 3.14;
cptr = &dval; //ok, but can not change dval through cptr
但是,我们不能够保证指向const的指针所指对象的值一定不可修改。
2)const指针
int errNumb = 0;
int *const curErr = &errNumb; //curErr is a constant pointer
从右向左把上述定义读作“curErr是指向int 型对象的const 指针”
3、指向const对象的const指针
4、指针和typedef
在typedef中使用指针往往会带来意外的结果。
typedef string *pstring;
const pstring cstr;
请问cstr变量是什么类型?
很多人都会认为真正的类型是:
const string *cstr;也就是说,const pstring是一种指针,指向string类型的const对象,
但是:这是错误的!!!
错误的原因:
将typedef当做文本拓展了。声明const pstring时,const修饰的是pstring的类型,这是一个指针。因此,该声明语句应该是把cstr定义为指向string类型对象的const指针,这个定义等价于:
//cstr is a const pointer to string
string *const cstr;
建议:
理解复杂的const类型的声明
阅读const声明语句产生的部分问题,源于const限定符既可以放在类型前也可以放在类型后:
string const s1;
const string s2; //s1 and s2 both strings that are const
用typedef写const类型定义时,const限定符加在类型名前面容易引起对所定义的真正类型的误解:
string s;
typedef string *pstring;
const pstring cstr1 = &s;
pstring const cstr2 = &s;
string *const cstr3 = &s;
把const放在类型pstring之后,然后从右向左阅读该声明语句就会非常清楚的知道cstr2是const pstring类型,即指向string对象的const指针。