C++|指针、智能指针学习说明


每一个变量都有一个内存位置,每一个内存位置都定义了可使用(&)运算符访问的地址,它表示了在内存中的一个地址。

堆指针/栈指针

堆指针:

申请动态分配,它的值放到堆中。
int p; p=new int;
new返回新分配的内存单元的地址。
因为其地址已经动态分配,所以可以
p=22,这样直接赋值。

栈指针:

没有申请动态分配,它的值放到栈中。
int p; int a=22; p=&a;
指针p获取了栈中a的地址,属于静态分配,对
p的操作等于对a的操作。

堆和栈的区别:

  1. 堆由程序员控制(malloc/free)(new/delete)
    栈由编译器自动管理
  2. 堆 不连续 大 灵活
    栈 连续 大小由操作系统预定号
  3. 堆 频繁的new/delete会造成大量内存碎片,降低了程序效率。
    栈 先进后出的结构,进出一一对应,不会产生碎片。
  4. 堆 向上 向高地址方向增长
    栈 向下 向低地址方向增长

内存泄漏:

是指程序申请内存后,无法释放已申请的内存空间,内存泄漏多了会导致可用内存空间变小,进一步造成内存溢出。

空指针:

NULL指针是一个定义在标准库中的值为零的常量。
ptr=0表示该指针不指向一个可访问的内存位置。

各类型变量所占字节数

类型字节数
char1
short int2
int4
long int8
long long int8
char *8
float4
double8

指针的算术运算:

  1. 加减:若pr指向一个整数指针,pr++会让地址加4。
  2. 比较:如果pr1和pr2指向的两个相关的变量,比如同一个数组中的不同元素,则可对p1和p2进行大小比较。

指针与数组:

var[3]={1,2,3};
*(var+2)=300;
相当于var[2]=300;

char*是指向字符串的指针(指向字符串的首个字母),可以指向一串常量字符串。
例:
char a[3]={‘a’,‘b’,‘c’};
char * a[3]={“aa”,“bb”,“cc”};
a[0]=“a” 因为a[0]代表指向字符串的首地址(首个字母)

  1. char* const[指向字符的静态指针]
    const修饰指针,代表不能改变指针
  2. const char * 指向静态字符的指针
    const修饰char,代表字符不能改变,但是指针可以变,也就是说该指针可以指向其他const char。

char[]和char *
char * a= “string”
char b[]=“stirng”
a是一个char型指针变量,其值(指向可以改变)
b是一个char型数组的名字,也是该数组首元素的地址,其值不可变
a=b; //a,b指向同一区域
char * 本身是一个字符指针变量,但是它既可以指向字符串常量,又可以指向字符串变量,指向的类型决定了对应字符能不能改变,所以若没有对a进行操作的意向,尽量定义为const char *a =“string”;

强指针与弱指针

强指针/强引用:A指向B, A可以决定B的生死(就是会触发incStrong()/decStrong()被调用)
弱指针/弱引用:A指向B, 但是A不可以决定B的生死(弱指针的引用不会修改mCount引用计数,因此也不能通过弱指针引用对象成员)
使用范围:
强:局部变量,子对象指针,可影响其生命周期的指针
弱:父对象指针,某些不能影响其生命周期的对象
作用:
强:利用强指针进行资源回收,不需要再人工计算new和delete,一个对象在何处(父类或函数中)创建,就在何处(父类或函数结束)回收
弱:一是避免强指针循环依赖,二是保障线程安全,其他对象成员不是在该类中创建,则不需要该类负责回收,因此使用弱指针。

参考:深入实践C++11智能指针
https://blog.csdn.net/code_peak/article/details/119722167?spm=1001.2014.3001.5501

智能指针:

C++里面的四个智能指针: auto_ptr, unique_ptr,shared_ptr, weak_ptr 其中后三个是C++11支持,并且第一个已经被C++11弃用。

unique_ptr:

(替换auto_ptr)unique_ptr实现独占式拥有或严格拥有概念,保证同一时间内只有一个智能指针可以指向该对象。它对于避免资源泄露(例如“以new创建对象后因为发生异常而忘记调用delete”)特别有用。

unique_ptr<string> str1 (new string ("auto"));   
unique_ptr<string> str2;            
str1 = str2;//此时会报错!!

当程序试图将一个 unique_ptr 赋值给另一个时,如果源 unique_ptr 是个临时右值,编译器允许这么做;如果源 unique_ptr 将存在一段时间,编译器将禁止这么做,比如:

unique_ptr<string> str1(new string ("hello world")); 
unique_ptr<string> str2; 
str1= str2;     //不允许
unique_ptr<string> str3; 
str3= unique_ptr<string>(new string ("test"));   //允许

shared_ptr

shared_ptr实现共享式拥有概念。多个智能指针可以指向相同对象,该对象和其相关资源会在“最后一个引用被销毁”时候释放。它使用计数机制来表明资源被几个指针共享。可以通过成员函数use_count()来查看资源的所有者个数。除了可以通过new来构造,还可以通过传入auto_ptr, unique_ptr,weak_ptr来构造。当我们调用release()时,当前指针会释放资源所有权,计数减一。当计数等于0时,资源会被释放。
成员函数:

  • use_count 返回引用计数的个数
  • unique 返回是否是独占所有权( use_count 为 1)
  • swap 交换两个 shared_ptr 对象(即交换所拥有的对象)
  • reset 放弃内部对象的所有权或拥有对象的变更, 会引起原有对象的引用计数的减少
  • get 返回内部对象(指针), 由于已经重载了()方法, 因此和直接使用对象是一样的

weak_ptr:

share_ptr虽然已经很好用了,但是有一点share_ptr智能指针还是有内存泄露的情况,当两个对象相互使用一个shared_ptr成员变量指向对方,会造成循环引用,使引用计数失效,从而导致内存泄漏。

weak_ptr 是一种不控制对象生命周期的智能指针, 它指向一个 shared_ptr 管理的对象. 进行该对象的内存管理的是那个强引用的shared_ptr, weak_ptr只是提供了对管理对象的一个访问手段。weak_ptr 设计的目的是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少。weak_ptr是用来解决shared_ptr相互引用时的死锁问题,如果说两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能下降为0,资源永远不会释放。它是对对象的一种弱引用,不会增加对象的引用计数,和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给它,它可以通过调用lock函数来获得shared_ptr。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奇树谦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值