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

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

时间:2023-05-03 23:33:15浏览次数:35  
标签: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://blog.51cto.com/u_15950321/6241649

相关文章

  • C++中的智能指针和内存管理
    C++是一门强大的编程语言,但是在内存管理方面却存在着一些问题。手动管理内存不仅费时费力,而且容易出错。因此,C++中引入了智能指针这一概念,以更好地管理内存。什么是智能指针?在C++中,内存的分配和释放都是由开发者手动实现的。这种方式虽然很灵活,但也十分容易出错,比如忘记释放内......
  • 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类型,但无法修改......