C++ 指针
指针的使用、使用new创建动态数组、使用delete释放内存
#include <iostream>
using namespace std;
// ----------------------------------指针-------------------------------------
void pointer(){
int updates = 6;
int * p_updates;
p_updates = & updates;
cout << "Value:updates = " << updates << endl;
cout << "*p_updates = " << *p_updates << endl;
cout << "Address:&updates = " << &updates << endl;
cout << "p_updates = " << p_updates << endl;
// 程序输出:
// Value:updates = 6
// *p_updates = 6
// Address:&updates = 0xffffcbd4
// p_updates = 0xffffcbd4
// int变量updates和指针变量p_updates只不过是一枚硬币的两面。变量updates表示值,并使用&操作符来获得地址;
// 而变量p_updates表示地址,并使用*操作符来取值,由于p_updates指向updates,因此*p_updates和updates
// 完全等价。可以像使用int变量那样使用*p_updates。
// 指针的定义-*号操作符两边的空格是可选的
int *ptr;
int* psr;
// 每个指针变量的创建都需要一个*,下面的例子将创建一个指针p1和一个int变量p2
int *p1, p2;
// 使用new关键字为指针分配内存
// 在C语言中可以使用库函数malloc()来分配内存,在C++中还有更好的方法——使用new操作符
int *pt = new int;
// 内存耗尽
// 计算机可能会由于没有足够的内存而无法满足new的请求,在这种情况下,new将返回0,在C++中,值为0分指针
// 被称为空指针null pointer,C++确保空值指针不会指向有效的数据,因此它常被用来表示操作符或函数失效,
// 如果成功,将返回一个有用的指针。
// 使用delete来释放内存
// 当需要内存时,可以使用new来请求,这只是C++内存管理数据包中有魅力的一个方面。另一个方面是delete操作符,
// 它使得在使用完内存后,能够将其归还给内存池,这是通向最有效地使用内存的关键一步。归还或释放free的内存可供
// 程序的其他部分使用。使用delete时,后面要加上指向内存块的指针(这些内存块最初是用new分配的)
// **注意:只能用delete来释放使用new分配的内存。不过对空指针使用DELETE是安全的。
// 这将释放ps指向的内存,但不会删除指针ps的本身,例如,可以将ps重新指向另一个新分配的内存块,一定要配对
// 地使用new和delete。否则程序将发生内存泄露memory leak,也就是说,被分配的内存再也无法使用了;如果
// 内存泄露严重,则程序将由于不断寻找更多内存而终止
int *p3 = new int;
delete p3;
// 不要尝试释放已经释放的内存块,C++标准指出,这样做的结果将是不确定的,这意味着什么情况都可能发生。另外
// 不能使用delete来释放声明变量所获得的内存;
// int *p4 = new int;
// delete p4;
// delete p4; //not ok now,不能重复释放已经释放的内存块
// int jugs = 5;
// int *p5 = &jugs;
// delete p5; //不能delete来释放声明变量所获得的内存;
// **注意,使用delete的关键在于,将他用于new分配的内存,这并不意味着要使用用于new的指针,而是用于new的地址
// 一般来说,不要创建两个指向同一个内存块的指针,因为这将增加错误地删除同一个内存块两次的可能性
// int *p6 = new int;
// int *p7 = p6;
// delete = p6;
// 使用new创建动态数组
// 在C++中,创建动态数组很容易,只要将数组的元素类型和元素数目告诉new即可,必须在类型名后加上[],其中包含元素数目
int *psome = new int[10];
// new操作符返回第一个元素的地址,在这个例子中,该地址被赋给指针psome,当程序结束后,应使用DELETE释放
// 指针数组的使用
psome[0] = 0;
psome[1] = 2;
psome[2] = 3;
cout << "psome[0] = " << psome[0] << endl;
cout << "psome[1] = " << psome[1] << endl;
cout << "psome[2] = " << psome[2] << endl;
// psome[0] = 0
// psome[1] = 2
// psome[2] = 3
psome = psome + 1;
cout << "psome[0] = " << psome[0] << endl;
cout << "psome[1] = " << psome[1] << endl;
// psome[0] = 2
// psome[1] = 3
// 指针返回到开始
psome = psome - 1;
// 不能修改数组名的值,但指针是变量,因此可以修改他们的值。将psome + 1的效果,表达式psome[0]现在指向的是
// 数组的第二个值,因此将psome + 1导致它指向第二个元素而不是第一个。将它减一后,指针将指向原来的值
// 在释放new创建的动态数组时,应使用另一种格式的delete,它能够指出所要释放的是一个数组
// []会告诉程序,应释放整个数组,而不仅仅是指针指向的元素
delete[] psome;
// 使用new和delete时,应遵守以下规则:
// 1、不要使用delete来释放不是new分配的内存
// 2、不要使用delete释放同一个内存两次
// 3、如果使用new []为数字分配内存,则应使用delete[]来释放
// 4、如果使用new []为一个实体分配内存,则应使用delete来释放
// 5、对空指针应用delete是安全的
// 将指针变量加一后,其增加的值等于指向类型占用的字节数
// stacks[1]可以看作是* (stacks + 1),这意味着先计算第二个元素的地址,然后找到存储在那里的值。
// 最后输出存储在那里的值。
char flower[10]= "rose";
cout << flower << endl;
cout << &flower << endl;
}
int main() {
pointer();
return 0;
}
使用new创建动态结构、使用delete释放new创建的动态结构的内存、使用->访问指针指向的结构体变量
#include <iostream>
using namespace std;
// 动态结构
void structure(){
struct things{
int good;
int bad;
};
things grubonse = {3, 453};
things *pt = &grubonse;
// 如果结构体标识符是结构名,则使用句点操作符
// 如果标识符是指向结构的指针,则使用箭头操作符
cout << "ps.good = " << pt->good << endl;
cout << "ps.bad = " << pt->bad << endl;
// 使用new创建结构体变量
person *person2 = new person;
person2->name = "fc";
person2->age = 18;
cout << "person2.name = " << person2->name << endl;
cout << "person2.age = " << person2->age << endl;
// 释放使用new创建的动态结构的空间
delete person2;
}
int main() {
structure();
return 0;
}
指针函数的定义、赋值、调用
// 定义指针函数
// 指针函数声明时需要将*和函数名括起来,括号优先级比*操作符高,因此*fun (int)代表返回指针的函数,
// 而(*fun) (int)意味着fun是一个指向函数的指针
double pam(int);
double (*pf) (int);
// 指针函数的赋值,将pam函数的地址赋给pf,赋值函数和指针函数的返回值类型编写相同才能赋值
// pf = pam;
// 指针函数的调用
double x = pam(3);
double y = (*pf)(5);