第八章 指针
2. 用指针来保存地址
☆指针就是保存内存地址的无符号整数变量
指针,是一个无符号整数(unsigned
int),它是一个以当前系统寻址范围为取值范围的整数。32位系统下寻址能力(地址空间)是4G-byte(0~2^32-1)二进制表示长度为32bit(也就是4B)。64位系统下寻址能力(地址空间)是8G-byte(0~2^32-1)二进制表示长度为64bit(也就是8B)。
int a=1;
int *p=&a;等价于int *p;p=&a;
1. 空指针
将一个没有赋初值的指针delete,将会出现系统崩溃
☆定义指针后必须要对其初始化,或被赋值int *p=NULL;
0(NULL)既能是int型也可以是地址类型 int *型 所以0常常用于指针的初始化int
*p=0;此时的0代表地址为00000000的地址,并且这个地址不存储任何数据。我们大可以对它进行任意的操作。
4. 指针与类型
不能将不同类型指针(地址)相互赋值
6. 容易混淆的概念
p的值(p)≠p的地址(&p)
一个是存储的别人地址一个是自己的地址
7. 指针对数值的操作
typedef unsigned short int ut;
8. 更换指针保存的地址
和变量一样指针也可以更换其保存的地址
☆9.1. 为什么使用指针
1.处理堆中存放的大型数据
2.快速访问类的成员数据和函数
3.以别名的方式向函数传递参数(按址传递①改变实参的值②得到多个返回值)
堆中数据的优点:
①安全(只能通过指针来访问这些匿名的数据)②程序员可以控制这些数据的寿命
9.4. 指针与堆
9.5. 用指针删除堆中空间
☆声明了一个堆内存,就必须记得将他释放!
一般来说用于指向堆中内存的指针是个局部变量(存储在栈中),在程序结束并返回时,该指针就会自动消失。如果不提前delete或转移该地址,就会出现内存泄露(即内存遗落)
#include <iostream>
using namespace std;
int main()
{
int *p=new int;//堆的申请
*p=3600;
cout<<*p<<endl;
delete p;
cout<<*p<<endl;
//delete p;//连着两个delete系统就会崩溃,这是因为p指针指向的内存已经释放,再次释放就会导致系统崩溃
p=0; //必须使用,delete之后的未知堆中数据容易出错 注意
这个不是赋值而是将变量p的设为空指针(此处没体现这个必要性,但这是一个习惯,必须要养成)
p=new int;
*p=8;
cout<<*p<<endl;
delete p;
return 0;
}
10. 内存泄露
int *p=new int;
p=new int;(编译器不会报错)
delete p;//必须使用,否则就内存泄露,在使用new以后,不再使用该块内存空间,那么一定要用delete来释放它
11. 在堆中创建对象
Human *p=new human
12. 在堆中删除对象
13. 访问堆中的数据成员
☆(*p).get();等价于p->get();
14. 在构造函数中开辟内存空间
15. 对象在栈与堆中的不同
对象在栈中有析构函数自动释放内存,
对象在堆中要程序员手动释放该内存。
16. this指针
this指针 就是系统自动创建的指向对象的指针
☆17. 指针的常见错误
delete p 与 p=0 必须一起用
delete p后告诉编译器两件事:①p成了迷途指针②p指向的内存已被释放。
但是该p仍然指向这块内存,如果该内存被其它指针使用再次操作该p就会改变这个该内存的值
18. 指针运算 (即指针保存的内存地址的运算)
指针只能p++、p- -、p=p-2、p1=p2、*p=p1-p2(结果不是地址,是一个值,是两个内存地址的差)、P1>P2。
注意:因为开辟的内存不会自己改变,所以改变指针p后,p就不在指向这个内存空间。
19.1. 常量指针
int * const p (p的值不能改变,此时p只能被初始化不能被赋值)
目的在于将p与对象绑定
19.2. 指向常量的指针
Const int *p
目的在于将p绑定的对象设为常量
19.3. 指向常量的常指针
Const int * const p
目的在于将p与对象绑定并且将对象设为常量
以上操作都没有涉及到&p!!!
本章总结:
1. 指针是保存内存地址的变量(指针,是一个无符号整数(unsigned int))
int
a=1;
等价于
int a=1;
int*
p;
int* p=&a;
p=&a;
2. ☆指针从出现到消失,都要绑定一个已知对象的地址
一般情况下,指针常与NULL(0)地址为00000000的空间绑定;p=0;/p=NULL;
3. 为什么要使用指针
① 处理堆中大型数据
② 快速访问类的成员函数和数据
③ 按址传递①改变实参的值②得到多个返回值
4. 堆中数据的优点
① 安全(只能通过指针访问)②可以随时控制这些数据的寿命
5. 在堆中创建对象
human* p=new human;
创建一个human对象并且将地址传给p, *p就是该对象;
☆(*p).get();
等价于 p->get();
6. this指针:每个对象都有一个系统自创的this指针
7. ☆delete p 。告诉编译器两件事①p指向的空间被释放②p成了迷途指针
8. 指针运算。(由其类型而定)
指针只能:p++,p--,p=p-2,p1=p2,*p=p1-p2,p1>p2
☆指针的值改变后就不再指向原来的空间了
9. int* const p;
int const *p;
等价于 const int * p;
int const * const p; 等价于
const int * const p;
int get()const{x=5;return x;}