首页 > 编程语言 >从稍微懂一点开始的C++学习之路1: 智能指针

从稍微懂一点开始的C++学习之路1: 智能指针

时间:2022-12-07 20:12:55浏览次数:49  
标签:std p4 稍微 C++ 内存 shared ptr 指针

从稍微懂一点开始的C++学习之路1 智能指针

因为之前一直是搞qt的,没有搞过纯c++,所以现在算得上是刚开始学纯C++。C++的大部分语法其实我都懂,主要的是一些规范,还有内存回收等一些细节地方纯C++和Qt之间还是有蛮大差距的,现在底层框架需要用纯C++进行开发,所以这里我就重新学一下C++这门语言。

 

基础的语法就不再去详细了解了,现在从一些机制开始聊起,看到哪算哪,感觉有意思的就记一下。

今天聊聊智能指针

在实际的 C++ 开发中,我们经常会遇到诸如程序运行中突然崩溃、程序运行所用内存越来越多最终不得不重启等问题,这些问题往往都是内存资源管理不当造成的。比如:

  • 有些内存资源已经被释放,但指向它的指针并没有改变指向(成为了野指针),并且后续还在使用;
  • 有些内存资源已经被释放,后期又试图再释放一次(重复释放同一块内存会导致程序运行崩溃);
  • 没有及时释放不再使用的内存资源,造成内存泄漏,程序占用的内存资源越来越多。

针对以上这些情况,很多程序员认为 C++ 语言应该提供更友好的内存管理机制,这样就可以将精力集中于开发项目的各个功能上。

 

C++ 智能指针底层是采用引用计数的方式实现的。简单的理解,智能指针在申请堆内存空间的同时,会为其配备一个整形值(初始值为 1),每当有新对象使用此堆内存时,该整形值 +1;反之,每当使用此堆内存的对象被释放时,该整形值减 1。当堆空间对应的整形值为 0 时,即表明不再有对象使用它,该堆空间就会被释放掉。

注意本文的智能指针需要用到

  1. #include <memory>
  2. using namespace std

请不要忘记这点

1.shared_ptr

shared_ptr就是可以共享的指针,和 unique_ptr、weak_ptr 不同之处在于,多个 shared_ptr 智能指针可以共同使用同一块堆内存。并且,由于该类型智能指针在实现上采用的是引用计数机制,即便有一个 shared_ptr 指针放弃了堆内存的“使用权”(引用计数减 1),也不会影响其他指向同一堆内存的 shared_ptr 指针(只有引用计数为 0 时,堆内存才会被自动释放)。

1、shared_ptr智能指针的创建

shared_ptr<T> 类模板中,提供了多种实用的构造函数,这里给读者列举了几个常用的构造函数(以构建指向 int 类型数据的智能指针为例)。

1)  通过如下 2 种方式,可以构造出 shared_ptr<T> 类型的空智能指针:

  1. std::shared_ptr<int> p1; //不传入任何实参
  2. std::shared_ptr<int> p2(nullptr); //传入空指针 nullptr

注意,空的 shared_ptr 指针,其初始引用计数为 0,而不是 1。

2) 在构建 shared_ptr 智能指针,也可以明确其指向。例如:

  1. std::shared_ptr<int> p3(new int(10));

由此,我们就成功构建了一个 shared_ptr 智能指针,其指向一块存有 10 这个 int 类型数据的堆内存空间。

同时,C++11 标准中还提供了 std::make_shared<T> 模板函数,其可以用于初始化 shared_ptr 智能指针,例如:

  1. std::shared_ptr<int> p3 = std::make_shared<int>(10);

以上 2 种方式创建的 p3 是完全相同。

3) 除此之外,shared_ptr<T> 模板还提供有相应的拷贝构造函数和移动构造函数,例如:

  1. //调用拷贝构造函数
  2. std::shared_ptr<int> p4(p3);//或者 std::shared_ptr<int> p4 = p3;
  3. //调用移动构造函数
  4. std::shared_ptr<int> p5(std::move(p4)); //或者 std::shared_ptr<int> p5 = std::move(p4);

如上所示,p3 和 p4 都是 shared_ptr 类型的智能指针,因此可以用 p3 来初始化 p4,由于 p3 是左值,因此会调用拷贝构造函数。需要注意的是,如果 p3 为空智能指针,则 p4 也为空智能指针,其引用计数初始值为 0;反之,则表明 p4 和 p3 指向同一块堆内存,同时该堆空间的引用计数会加 1。

而对于 std::move(p4) 来说,该函数会强制将 p4 转换成对应的右值,因此初始化 p5 调用的是移动构造函数。另外和调用拷贝构造函数不同,用 std::move(p4) 初始化 p5,会使得 p5 拥有了 p4 的堆内存,而 p4 则变成了空智能指针。

 

注意,同一普通指针不能同时为多个 shared_ptr 对象赋值,否则会导致程序发生异常。例如:

 

int* ptr = new int;
std::shared_ptr<int> p1(ptr);
std::shared_ptr<int> p2(ptr);//错误


4) 在初始化 shared_ptr 智能指针时,还可以自定义所指堆内存的释放规则,这样当堆内存的引用计数为 0 时,会优先调用我们自定义的释放规则。

在某些场景中,自定义释放规则是很有必要的。比如,对于申请的动态数组来说,shared_ptr 指针默认的释放规则是不支持释放数组的,只能自定义对应的释放规则,才能正确地释放申请的堆内存。

对于申请的动态数组,释放规则可以使用 C++11 标准中提供的 default_delete<T> 模板类,我们也可以自定义释放规则:
//指定 default_delete 作为释放规则
std::shared_ptr<int> p6(new int[10], std::default_delete<int[]>());

//自定义释放规则
void deleteInt(int*p) {
    delete []p;
}
//初始化智能指针,并自定义释放规则
std::shared_ptr<int> p7(new int[10], deleteInt);

标签:std,p4,稍微,C++,内存,shared,ptr,指针
From: https://www.cnblogs.com/Leventure/p/16964390.html

相关文章

  • [c++11新特性]12-类型萃取
    ​​c++11/14类型萃取​​类型萃取所谓类型萃取,就是依靠模板的方式,来判断一个类型是否拥有某些特性,比如A类型和B类型是否相同,C类型是否有某个成员变量,D类型是否有某个方法,或......
  • 【C语言】* 和 & 认识、对解引用(*)认识、* & 的应用、通过指针交换变量值、指针变量
    ......
  • 算法练习:两指针之三数之和为0
    问题描述给出一个整型数组,找出所有三个元素的组合,其组合之和等于0。要求在结果集里不含有重复的组合。举例:输入{-2, 1, -1, 2, 1}输出{-2, 1, 1 } 问题分析最容易想到的是......
  • C/C++计时函数
    计时函数介绍time函数原型`time_ttime(time_t*timer)`,time函数是c-runtime库里的函数。此函数返回从1970年1月1日00:00:00(UTC时间)到此刻所经过的总秒数,所以使用此函数......
  • 无法在Unreal Engine中使用C++创建Struct
    1)无法在UnrealEngine中使用C++创建Struct​2)Unreal中,如何在一个视口内显示多个摄像机视口3)如何能和UGUI里面的图片做个动画一直旋转,实现Loading效果4)UIToolkit中ListView......
  • c++练习272题:金币
    *272题原题传送门:http://oj.tfls.net/p/272题解:(遍历,60分)#include<bits/stdc++.h>usingnamespacestd;longlongallday;//总天数longlongpas;//已经过去longlongmo......
  • 私有继承和保护继承的访问规则是什么?c++
    以这些类为例:classB{/*...*/};classD_priv:privateB{/*...*/};classD_prot:protectedB{/*...*/};classD_publ:public......
  • 算法练习:两指针之有序数组去重
    问题描述给出一个有序数组,就地移除重复元素,保持每个元素只出现一次,并返回新数组的长度。 问题分析这个比较简单,直接使用两个指针,一个在前,一个在后,扫描一遍数组即可。时间复......
  • 算法练习:两指针之三色排序
    问题描述输入一个整型数组,每个元素在0~2之间,其中0,1,2分别代表红、白、蓝。现要求对数组进行排序,相同颜色的在一起,而且按红白蓝顺序先后排列。要求时间复杂度为O(n)。 问题分......
  • C++知识点:数组末端下一位置
    c++语言规定,数组末端下一位置是合法的,但不允许对其解引用(即解引用是未定义的)。......