C++复习笔记
c++ primer笔记
指针(二)
指针操作
- 生成左值的解引用操作
可以利用解引用操作符返回指向对象的左值,可以利用这个修改指针所指向对象的值。
string s("hello world!!");
string *sp = &s; //此时sp指向的对象的值是hello world!!
*sp = "goodbye!!"; //此时sp指向的对象的值是goodbye!!
-
指针和引用
两者有两个重要的区别:
a)引用总是指向某个对象,定义引用时没有初始化是错误的(因为引用相当于对象的一个别名,一定要在定义是就知道是哪个对象的别名)。但是指针定义时可以不初始化,不过不对指针赋值会造成悬垂指针,会引发严重得运行时错误。所以建议在指针定义时就对其初始化。
b)赋值行为的差别
给引用赋值修改的是该引用所关联的对象的值,而并不是使引用与另一个对象相关联。引用一旦初始化就始终指向同一个特定的对象,而指针可以修改所指向的对象。 -
指向指针的指针
这里不是“套娃”啊。其实这里是把指针类型也当作一种数据类型,指针本身也是可以用指针指向的内存对象。
int ival = 1024; //int型变量
int *pi = &ival; //指向int型变量的指针
int **ppi = π //指向int型指针的指针
使用指针访问数组元素
数组名还有另外一个功能就是在表达式中,数组名会自动转化为指向数组中第一个元素的指针。
- 指针的算术运算
使用指针的算数运算操作在指向数组的某个元素的指针上加上(减去)一个整型数值,就可以得到数组中另一个元素的指针值。
int ia[] = {1,2,3,4,5};
int *ip = ia; //ip = &ia[0];
int *ip2 = ip + 2; //ip2 = &ia[2];
注意:指针的算术操作只有在原指针和计算出来的新指针指向同一个数组的元素,或者只想该数组存储空间的下一格单元时才合法。
同时指针也支持两个指针之间的减法运算。
两个指针相减得到的是ptrdiff_t类型的数据,此类型用于存放同意数组的两个指针之间的差距,可正可负。
ptrdiff_t n = ip2 - ip; //指针ip2和ip之间的差距
- 解引用和指针算术运算
由于指针算术运算得到的也是一个指针,所以允许在这个结果上直接进行解引用操作。
int ia[] = {1,2,3,4,5};
int last = *(ia + 4);
注意这里一定要加括号,因为加法操作的优先级大于解引用操作。如果不加括号就是先对ia解引用,然后将得到的值+4赋值给last。
- 计算数组的超出末端指针
在迭代器中提到过end函数,返回的是vector容器的末尾元素的下一个位置。同样的,C++允许计算数组或者对象超出末端的地址,但是不允许对指针进行解引用操作。
可以粗略地认为指针就是数据的迭代器。
指针与const限定符
- 指向const对象的指针
前面说可以通过指针解引用操作改变指针所指向的对象的值,但是如果指针指向的是const对象,也不允许通过指针修改所指向的对象的值。
const double *ptr;
ptr是一个指向double类型const对象的指针,指向的对象的值是不可以改变的,但是指针ptr的值是可以修改的。
把一个const对象的地址赋值给不指向const对象的指针是非法的;但是把一个非const对象的地址赋值给指向const对象的指针则是可以的。需要注意的是,这个非const对象的值是可以修改的,但是不可以通过这个指针进行修改。
我们可以把指向const的指针理解为自以为指向了const对象的指针。
- const指针
const指针和其他const对象一个样,必须要在定义时初始化,这一点有些与引用相似。
int test = 1024;
int *const pi = &test; //const指针
这里的const修饰的是指针修饰的是指针,即指针的指向是不可以修改的,但是指针所指向的对象的值是可以修改的。
- 指向const对象的const指针
就是将前两种结合到一起,既不可以修改值,也不可以修改指针。
C风格字符串
简单说,字符串字面值就是一种C风格字符串。C风格字符串是以空字符null结束的字符数组。
char ca1[] = {'c','+','+'};
char ca1[] = {'c','+','+','\0'};
char ca1[] = "c++"
const char *cp = "c++";
char *cp1 = ca1;
char *cp2 = ca2;
ca1和cp1都不是c风格字符串,其余都是。
- c风格字符串的标准库函数
使用这些库函数需要包含以下头文件
#include <cstring>
函数定义 | 功能 |
---|---|
strlen(s) | 返回s的长度,不包括字符串结束符null |
strcmp(s1,s2) | 比较两个字符串s1和s2是否相同。如果相等则返回0;如果s1大于s2则返回中正数;如果s1小于s2则返回负数 |
strcat(s1,s2) | 将字符串s2连接到s1的后面,返回s1 |
strcpy(s1,s2) | 将s2复制给s1,返回s1 |
strncat(s1,s2,n) | 将s2的前n个字符连接到s1后面,返回s1 |
strncpy(s1,s2,n) | 将s2的前n个字符复制到s1,返回s1 |
注意,这些标准库函数不会检查字符串参数。
- 永远不要忘记字符串结束符null
标准库函数strlen函数假定其参数字符串是以null字符结束的。
一般来说,strncpy和strncat函数要比strcpy和strcat更安全。