指针是一个变量,其存储的是值的地址,而不是值本身
1 | int * p_updates; |
* p_updates
的类型为int
,不是指针p_updates
的类型是int *
,是指向int
的指针
指针在地址中的存储格式
1 | int ducks = 12; |

ducks
的地址是 0x1000
,存储的值是 12。而 birddog
的地址是 0x1006
,存储的值就是 ducks
的地址 0x1000
指针变量的声明
1 | int a = 12; |
输出结果
1 | 100 |
从结果来看:
- 声明的时候
int *p1, p2;
,声明的是两种类型 - 当两个指针指向同一个地址时,修改一个会影响另外一个
既然是地址,是不是可以直接给地址复制,答案是可以的
1 | int * p3; |
不能直接将整型复制给指针,可通过类型转换赋值给 p3,但是会段错误(Segmentation fault),即未知的地址
new
在C语言中,可以 用库函数malloc( )
来分配内存;在C中仍然可以这样做,但C还有new
运算符
1 | int night = 1000; |
运行结果
1 | 1000 1001 |
地址本身只指出了对象存储地址的开始,而没有指出其类型(使用的字节数)。而通过
变量值都存储在被称为栈(stack)的内存区域中,而new从被称为堆(heap)或自由存储区(free store)的内存区域分配内存
在 C中,值为0的指针被称为空指针(null pointer)。C确保空指针不会指向有效的数据
归还或释放(free
)的内存可供程序的其他部分使用。使用 delete
时,后面要加上指向内存块的指针
1 | int *pt = new int; |
运行结果
1 | 0x7f93c3705ce0 |
-
使用
delete
仅会释放内存块,但是不会将指针的地址置为空 -
new
与delete
需要配合使用,否则将发生内存泄露(memory leak
) -
不能重复释放已经释放的内存块
delete
不能删除一个不是 new
分配的内存
1 | int a = 10; |
delete
能删除一个空指针
1 | int *pt2 = nullptr; |
动态数组
在编译时给数组分配内存被称为静态联编(static binding),在编写程序时指定数组的长度,意味着数组是在编译时加入到程序中的
还可以在程序运行时选择数组的长度,被称为动态联编(dynamic binding),程序将在运行时确定数组的长度,这种数组叫作动态数组(dynamic array)
在C++中,创建动态数组,只要将数组的元素类型和元素数目告诉new
即可
1 | int *psome = new int [10]; |
方括号告诉程序,应释放整个数组,而不仅仅是指针指向的元素。 注意delete
和指针之间的方括号
-
如果使用
new
时,不带方括号,则使用delete
时,也不应带方括号。 -
如果使用
new
时带方括号,则使用delete
时也应带方括号
1 | double * p1 = new double [3]; |
运行结果
1 | p1[1] is 0.3 |
注意在释放指针的时候执行了 p1 = p1 - 1;
否则会提示错误 error for object 0x7fe25e705ce8: pointer being freed was not allocated
将整数变量加 1 后,其值将增加1;但将指针变量加1后,增加的量等于它指向的类型的字节数。将指向double
的指针加1后,如果系统对double
使用8个字节存储,则数值将增加8;将指向short的指针加1后,如果系统对short使用2 个字节存储,则指针值将增加2
1 | double wages[3] = {10000.0, 20000.0, 30000.0}; |
运行结果
1 | 20000 |

数组名被解释为其第一个元素的地址,而对数组名应用地址运算符时,得到的是整个数组的地址:
总结
- 不要使用
delete
来释放不是new
分配的内存 - 不要使用
delete
释放同一个内存块两次 - 如果使用
new [ ]
为数组分配内存,则应使用delete [ ]
来释放。 - 如果使用
new
为一个实体分配内存,则应使用delete
(没有方括 号)来释放。 - 对空指针应用
delete
是安全的。
参考链接
- 《C++ Primer Plus》