一、指针的两种写法
①typename* ptr;②typename *ptr;
其中①是C的风格,强调* ptr是一个typename类型的值;②是C++中的写法,更趋向于把 typename *是一个类型,即指向typename的指针。这两种写法对于编译器来说无任何区别。
二、指针的危险
此处的危险是指,指针解引用前,必须为指针变量赋予确定的、适当的地址。否则会造成bug。如下代码是不允许的,通常这种代码是编译不过去的。
int *f;*f=232456;
三、new的使用规范
- 不要使用delete来释放不是new分配的内存;
- 不要使用delete释放同一内存块两次;
- 如果使用new[]为数组分配内存,则应使用delete[]来释放,尤其是用指针来实现的类,如string,必须配对使用,否则会造成内存泄漏;
- 如果使用new为一个实体分配内存,则应使用delete来释放;
- 对空指针应用delete是安全的。
四、 动态数组的注意事项
new出的动态数组返回的是数组的首地址,这与普通数组是一样的。与普通数组不一样的是动态数组可以修改数组名的值,而数组不可以。如下所示:
#include<iostream>
using namespace std;
int main(void) {
double *p = new double[3];//new 出3个double类型的空间
p[0] = 12.3;
p[1] = 23.3;
p[2] = 0.8;
cout << "p not move 1" << " p[0]:" << p[0] << " p[1]:" << p[1] << " p[2]:" << p[2] << endl;
p = p + 1;
cout << "p move 1" << " p[0]:" << p[0] << " p[1]:" << p[1] << "p[2]:" << p[2] << endl;
getchar();
}
执行结果:
可以看出p+1后,p的指向发生了变化。而普通数组的数组名+1再赋值给数组名后编译不通过,报表达式必须是可修改的左值的错,并不是说数组名自身不能加。**为什么报这个错?**因为数组名都表示数组第一个元素的地址,可将其看作是一个指针常量,常量是不能作为左值的。动态数组名之所以能进行赋值操作,因为它本身是个指针变量,只不过new后赋予了动态数组的首地址作为初值罢了。**同时用sizeof(数组名)获取的是数组的大小,而sizeof(pointer)获取的是指针的大小。
五、指针、数组与指针算术
5.1 数组的地址
数组名为数组首元素的地址,对数组名取地址,代表的是整个数组的地址。
举个例子来说明,假如有如下代码:
char p[3];
char *a = p;
void *aa = &p;
char (*aaa) [3]= &p;
从数字上说,a、aa和aaa三者的值相同,但是a+1表示移动了1个bit,移动的是char类型大小的字节;而aa+1和aaa+1移动的是整个数组的大小:即3*sizeof(char),因此&p指向的是包含3个元素的char数组(char( * )[3])。其实,aaa的类型就是char( * )[3]。
5.2 指针与字符串
cout输出是从给定的字符地址开始一直输出字符,直到遇到’\0’为止。应使用strcpy()或者strncpy(),而不是赋值运算符来将字符串赋给数组。