先来个简单的程序初步认识一下指针
#include "iostream"
using namespace std;
int main() {
// 定义一个int型变量
int num = 123;
// 定义一个int型指针变量
int * p_num;
// 指针指向num的地址
p_num = #
cout << "num = " << num << endl;
cout << "*p_num = " << *p_num << endl;
cout << "address of num is : " << &num << endl;
cout << "p_num = " << p_num << endl;
// 对p_num指向的地址里的数+1
// 那么num的值也+1, 因为p_num指向的就是num的内存地址
*p_num = *p_num + 1;
cout << "num = " << num << endl;
cout << "*p_num = " << *p_num << endl;
}
看运行结果:
注意使用指针的时候有个一定要注意的地方:一定要在对指针指向的内存进行赋值之前, 对指针的地址进行初始化, 否则我们就不知道所赋的值存储的具体位置是哪里, 因为指针没有被初始化, 所以指针指向的对我们来说是未知的地址, 而我们存储的数据也将是在那块未知的地址里. 举个例子:
long* p_longNum;
*p_longNum = 12345;
上面两行代码, 第一行声明了一个long型指针, 第二行把12345赋值给p_longNum所指向的地址, 但是问题是我们没有给p_longNum初始化地址, 所以我们不知道p_longNum指向了哪个地址, 也就是我们只初始化了指针变量, 而没有对其初始化, 那么p_longNum的值是内存当中原来已存在的数值, 这样会有一些隐患
c++里声明指针可以是一下几种方式:
int* p_num1;
int * p_num2;
int *p_num3;
int*p_num4;
int * p_num , 中间的空格可有可无
指针和数字
注意指针不是整型, 虽然计算机通常把地址当作整数来处理. 整数可以加减乘除等运算, 而指针描述的是位置, 因此将两个地址相乘没有任何意义.
int* pt;
pt = 0xB1000000;
看这个例子:虽然pt是一个int型指针, 可以给pt赋一个地址, 但是这条语句并没有告诉程序, 这个数字就是一个地址, 因此这样赋值编译机会报错:
所以如果我们想把一个整型地址复制给指针可以通过强制类型转换, 将数字转换为合适的地址类型例如:
int* pt;
pt = (int *)0xB1000000;
这样等号两边都是整数地址, 就可以有效赋值, 注意虽然pt是int型指针, 但是不代表pt本身的类型是int, 例如有些系统int占两个字节, 而指针占4个字节
C++中使用new来分配内存
c++中我们可以使用new来进行内存的分配 格式如下:
typeName * pinter_name = new typeName;
来看一个简单的例子:
#include "iostream"
using namespace std;
int main() {
int num = 1000;
// 声明一个int型指针
int* pt = new int;
// 给pt指针指向的内存里赋1000
*pt = 1000;
cout << "num is : ";
cout << num << " and num's location is : " << &num << endl;
cout << "int value is : " << *pt << " and it's location is " << pt << endl;;
// 声明一个double类型的指针变量, 并分配了内存空间
double * pd = new double;
// 给pd指针指向的内存里赋1000
*pd = 10000001.0;
cout << "double value is : " << *pd << " and it's location is : " << pd << endl;
cout << "location of pointer pd : " << &pd << endl;
cout << "size of pt = " << sizeof(pt) << endl;
cout << "size of pd = " << sizeof(pd) << endl;
cout << "size of *pt = " << sizeof(*pt) << endl;
cout << "size of *pd = " << sizeof(*pd) << endl;
return 0;
}
运行结果如下:
使用delete释放内存
当需要内存时,可以使用new来分配内存,当使用完内存后可以使用delete来释放new分配的内存,例如:
// 使用new给指针pn分配内存
int * pn = new int;
// 使用delete来释放pn指针指向的内存
delete pn;
注意:释放pn指向的内存,不会删除指针pn本身,也就是我们可以将pn重新指向另一个新分配的内存块. 一定要配对的使用new和delete,否则将会发生内存泄漏(memory leak), 也就是说被分配的内存再也无法使用了, 如果内存泄漏严重, 程序将因为分配不到新内存而终止.
另外不要尝试释放已经释放的内存块例如:
int * pn = new int;
// 正确
delete pn;
// 不正确, 因为pn已经释放过一次了
delete pn;
int num = 123;
int * pn2 = #
// 不正确, 因为pn的内存不是通过new来分配的
delete pn2;
注意:只能用delete来释放使用new分配的内存, 但是对空指针使用delete是安全的.
int * pn = new int;
int * pn2 = pn;
delete pn2;
上面的代码是没有问题的, 但是一般来说不要创建两个指向同一个内存的指针, 因为这将增加错误的删除同一个内存块两次的可能性