首页 > 系统相关 >C++中的智能指针和内存管理

C++中的智能指针和内存管理

时间:2023-05-03 23:23:26浏览次数:31  
标签:std C++ 智能 内存 shared ptr 指针

C++是一门强大的编程语言,但是在内存管理方面却存在着一些问题。手动管理内存不仅费时费力,而且容易出错。因此,C++中引入了智能指针这一概念,以更好地管理内存。

什么是智能指针?

在C++中,内存的分配和释放都是由开发者手动实现的。这种方式虽然很灵活,但也十分容易出错,比如忘记释放内存或释放了已经释放的内存等。为了避免这些问题,C++引入了智能指针这一概念。智能指针是一种类,它在析构时自动释放所管理的对象所占用的内存。这样,程序员就不需要手动管理内存,减少了出错的可能性。智能指针是一种RAII(Resource Acquisition Is Initialization)技术的应用。

RAII的基本思想是:在对象的构造函数中进行资源的分配,在析构函数中进行资源的释放。智能指针也是这种思想的一种扩展,它在析构时自动释放资源。

C++中的几种智能指针

C++中有三种智能指针:unique_ptrshared_ptrweak_ptr。每种智能指针都有其独特的功能和特点,下面将逐一介绍。

unique_ptr

unique_ptr是一个独享所有权的智能指针,不能共享所有权。当unique_ptr被销毁时,它所管理的对象的内存也会被自动释放。unique_ptr也可以通过std::move()转移所有权。unique_ptr使用的方法很简单,只需要将所需管理的对象传递给unique_ptr即可。

 #include <iostream>
 #include <memory>
 
 int main() {
     // 使用unique_ptr管理int类型的对象
     std::unique_ptr<int> up1(new int(10));
     std::cout << "up1: " << *up1 << std::endl;
 
     // 使用make_unique函数创建unique_ptr对象
     auto up2 = std::make_unique<int>(20);
     std::cout << "up2: " << *up2 << std::endl;
 
     // unique_ptr可以通过std::move()转移所有权
     std::unique_ptr<int> up3 = std::move(up1);
     std::cout << "up3: " << *up3 << std::endl;
 
     return 0;
 }

shared_ptr

shared_ptr是一个共享所有权的智能指针,可以有多个shared_ptr指向同一个对象。每当一个shared_ptr被销毁时,它所管理的对象的引用计数会减1。当引用计数为0时,对象的内存也会被自动释放。shared_ptr的使用方法和unique_ptr类似,只需要将所需管理的对象传递给shared_ptr即可。需要注意的是,shared_ptr不能管理动态分配的数组,因为它无法确定数组的长度。

 #include <iostream>
 #include <memory>
 
 int main() {
     // 使用shared_ptr管理int类型的对象
     std::shared_ptr<int> sp1(new int(10));
     std::cout << "sp1: " << *sp1 << std::endl;
 
     // 使用make_shared函数创建shared_ptr对象
     auto sp2 = std::make_shared<int>(20);
     std::cout << "sp2: " << *sp2 << std::endl;
 
     // 可以有多个shared_ptr指向同一个对象
     std::shared_ptr<int> sp3 = sp1;
     std::cout << "sp1 count: " << sp1.use_count() << std::endl;
     std::cout << "sp3 count: " << sp3.use_count() << std::endl;
 
     return 0;
 }

weak_ptr

weak_ptr是一个弱引用的智能指针,它可以与shared_ptr一起使用。weak_ptr不会增加所管理的对象的引用计数,因此它不会影响对象的生命周期。可以通过weak_ptrlock()成员函数来获取一个指向所管理的对象的shared_ptr。需要注意的是,在使用lock()函数之前,需要判断weak_ptr是否已经过期,即判断其指向的对象是否已经被销毁。

 #include <iostream>
 #include <memory>
 
 int main() {
     // 使用shared_ptr管理int类型的对象
     std::shared_ptr<int> sp1(new int(10));
     std::weak_ptr<int> wp1 = sp1;
 
     // 判断wp1是否过期
     if (auto sp2 = wp1.lock()) {
         std::cout << "wp1: " << *sp2 << std::endl;
     } else {
         std::cout << "wp1 expired" << std::endl;
     }
 
     // 销毁sp1
     sp1.reset();
 
     // 判断wp1是否过期
     if (auto sp2 = wp1.lock()) {
         std::cout << "wp1: " << *sp2 << std::endl;
     } else {
         std::cout << "wp1 expired" << std::endl;
     }
 
     return 0;
 }

总结

智能指针是C++中一种非常实用的内存管理工具。它可以帮助程序员自动管理内存,减少出错的可能性。C++中有三种智能指针:unique_ptrshared_ptrweak_ptr。每种智能指针都有其特点,程序员可以根据实际情况选择使用。

在使用智能指针时,需要注意以下几点:

  • 不要将普通指针和智能指针混用,避免重复释放内存或内存泄漏。
  • 不要将同一个对象交给不同的智能指针管理,避免引用计数出现错误。
  • shared_ptr不能管理动态分配的数组,因为它无法确定数组的长度。
  • 在使用weak_ptrlock()函数之前,需要判断weak_ptr是否已经过期,即判断其指向的对象是否已经被销毁。

使用智能指针可以大大提高代码的可读性和可维护性,建议大家在编写C++程序时多加使用。

标签:std,C++,智能,内存,shared,ptr,指针
From: https://www.cnblogs.com/xiaowange/p/17369890.html

相关文章

  • C++中的构造析构函数—2—虚析构函数
    1.构造函数不能定义为虚函数,每个对象的虚函数表指针是在构造函数中初始化的,因为构造函数没执行完,所以虚函数表指针还没初始化好。而析构函数可以定义为虚函数,也必须要定义为虚函数,否则在析构上无法体现出多态,导致子类的析构函数不会被调用,可能导致内存泄漏等风险。2.实验:#inc......
  • C语言--指针的进阶1
    数组指针:int*p[10];指向数组的指针。指针数组:int(*p)[10];存放指针的数组。voidprint1(intarr[3][5],intx,inty){ inti=0; intj=0; for(i=0;i<x;i++) { for(j=0;j<y;j++) { printf("%d",arr[i][j]); } printf("\n"); }}v......
  • C++ Primer 5th Edition, Chapter 2, Solutions
    Exercise2.1QuestionsWhatarethedifferencesbetweenint,long,longlong,andshort?Betweenanunsignedandasignedtype?Betweenafloatandadouble?SolutionsThosetypeshavedifferentminimumsizesaslistedinTable2.1.Andadditionalru......
  • C++ Primer 5th 阅读笔记:变量和基本类型
    一些语言的公共特性内建类型,如整型,字符型等;变量,为值绑定的一个名字;表达式和语句,操作值。分支和循环,允许我们条件执行和重复执行;函数,定义抽象计算单元。扩展语言的方式自定义类型;标准库。本章重点学习语言的基本知识和标准库。内建类型;简要介绍自定义类。类型......
  • 使用volatility dump从内存中重建PE文件——IAT函数出错的使用impscan解决
            好了,书中,说了操作的步骤,我们再vol2里实验下。查看进程:PSD:\Application\volatility3-stable>python.\vol.py-f"D:\book\malwarecookbook-master\malwarecookbook-master\16\7\laqma.vmem\laqma.vmem"windows.pslistVolatility3Fram......
  • java-对象在内存的运行机制
    面向对象Java是一种面向对象的编程语言。在Java中,一切都是对象,每个对象都有一组属性和方法。通过类来定义对象的属性和方法,一个类可以创建多个对象,每个对象都具有相同的属性和方法,但是它们的属性值可以不同。Java中的面向对象编程主要包括以下几个方面:封装:将对象的属性和方......
  • 为什么显卡的显存是1G 3G 6G 11G 22G 是奇数的倍数,而内存条是4G 8G 16G 32G 是偶数的
    为什么显卡的显存是1G3G6G11G22G是奇数的倍数,而内存条是4G8G16G32G是偶数的倍数  GPT4:显卡的显存和内存条的容量之所以有这种差异,主要原因是它们的设计和使用场景不同。内存条(RAM)通常使用二进制存储数据,因此其容量通常是2的整数次幂(如2、4、8、16、32等......
  • volatility 3 内存取证入门——如何从内存中寻找敏感数据
    volatility3内存取证入门——如何从内存中寻找敏感数据   上面说的思路,我自己在本机验证下,首先,我在虚拟机里使用IE登录我的qq邮箱,如下: 我自己登录IE的进程是2052,虚拟机dumpvmem文件以后,vol3下:python.\vol.py-f"D:\VirtualMachines\Windows10x641809\Win......
  • [c++]从完全不会到似懂非懂
    1.指针1.1指针常量使用int*constp=&a;的模式,指针常量是常量,所以p对应的常量为a的地址,因此a可变,但地址不可变。1.2常量指针使用constint*p=&a的模式,其实这里和const无关,p只是个指针,该指针的类型是constint类型,因此p可以修改指针指向其他的constint类型,但无法修改......
  • Java虚拟机之自动内存管理
    1内存区域1.1运行时数据区域运行时数据区域可以划分为由所有线程共享的方法区、堆和线程隔离的虚拟机栈、本地方法栈、程序计数器。1.1.1程序计数器(ProgramCounterRegister)-线程隔离程序计数器是一块较小的内存空间,它是当前线程所执行的字节码的行号指示器。Java虚拟机......