首页 > 编程语言 >C++智能指针

C++智能指针

时间:2023-09-16 23:55:37浏览次数:40  
标签:std 对象 C++ 智能 shared Foo ptr 指针

智能指针是C++语言中一种方便、安全的内存管理工具。智能指针可以自动管理对象的生命周期,避免手动分配和释放内存时可能出现的内存泄漏和悬挂指针等问题。在C++11标准中,引入了三种智能指针:unique_ptr、shared_ptr 和 weak_ptr。

类型 含义 备注
std::unique_ptr   独占资源所有权的指针。
std::shared_ptr   共享资源所有权的指针。
std::weak_ptr   享资源的观察者,需要和 std::shared_ptr 一起使用,不影响资源的生命周期。

unique_ptr 是一种独占式智能指针,它拥有对一个对象的唯一所有权,不能与其他智能指针共享对象所有权。当 unique_ptr 超出范围或被显式释放时,它所拥有的对象会被自动销毁。

shared_ptr 是一种共享式智能指针,它可以与其他 shared_ptr 共享一个对象。shared_ptr 使用引用计数技术来记录有多少个 shared_ptr 指向同一个对象,当引用计数为0时,对象会被自动销毁。

weak_ptr 是一种弱引用智能指针,它指向一个由 shared_ptr 管理的对象,但不会增加对象的引用计数。weak_ptr 用于解决循环引用问题,例如两个对象相互引用,导致它们的引用计数永远不会为0,从而无法自动销毁。

使用智能指针可以大大简化内存管理,减少内存泄漏和悬挂指针等问题。同时,智能指针还可以帮助程序员更好地编写多线程程序,避免竞态条件等问题。

下面是一个简单的示例程序,演示了如何使用 unique_ptr 和 shared_ptr:

 

 1 #include <iostream>  
 2 #include <memory>  
 3   
 4 struct Foo {  
 5     Foo() { std::cout << "Foo::Foo\n"; }  
 6     ~Foo() { std::cout << "Foo::~Foo\n"; }  
 7 };  
 8   
 9 int main() {  
10     std::unique_ptr<Foo> p1(new Foo); // 使用 unique_ptr 管理 Foo 对象的生命周期  
11     {  
12         std::shared_ptr<Foo> p2 = std::make_shared<Foo>(); // 使用 shared_ptr 管理 Foo 对象的生命周期  
13         {  
14             std::shared_ptr<Foo> p3 = p2; // p2 和 p3 共享 Foo 对象  
15         } // p3 超出范围,引用计数减1  
16     } // p2 超出范围,引用计数减1,Foo 对象被销毁  
17     // p1 超出范围,Foo 对象被销毁  
18     return 0;  
19 }

在上面的示例程序中,我们创建了一个 Foo 对象,并使用 unique_ptr 和 shared_ptr 来管理它的生命周期。在 p2 和 p3 共享 Foo 对象时,它们的引用计数都为2。当 p3 超出范围时,引用计数减1;当 p2 超出范围时,引用计数再减1,Foo 对象被自动销毁。最后,当 p1 超出范围时,Foo 对象再次被销毁。

除了unique_ptr和shared_ptr,C++还有weak_ptr,它是一种不控制对象生命周期的智能指针。它指向一个由shared_ptr管理的对象,但不会增加对象的引用计数。它主要用于解决循环引用问题,例如两个对象相互引用,导致它们的引用计数永远不会为0,从而无法自动销毁。

下面是一个使用weak_ptr的示例程序:

 1 #include <iostream>  
 2 #include <memory>  
 3   
 4 struct Foo {  
 5     void bar() { std::cout << "Foo::bar\n"; }  
 6     ~Foo() { std::cout << "Foo::~Foo\n"; }  
 7 };  
 8   
 9 int main() {  
10     std::shared_ptr<Foo> p1(new Foo); // 使用 shared_ptr 管理 Foo 对象的生命周期  
11     std::weak_ptr<Foo> wp1 = p1; // wp1 指向 p1 管理的 Foo 对象,但不增加引用计数  
12     {  
13         std::shared_ptr<Foo> p2 = wp1.lock(); // 使用 lock() 获取 shared_ptr  
14         if (p2) {  
15             p2->bar(); // 如果 p2 不为空,调用 bar() 函数  
16         }  
17     } // p2 超出范围,引用计数减1  
18     // wp1 超出范围,因为引用计数已经为0,所以 Foo 对象被销毁  
19     return 0;  
20 }

在这个示例程序中,我们创建了一个 Foo 对象,使用 shared_ptr 和 weak_ptr 来管理它的生命周期。weak_ptr 用于解决循环引用问题,因此它不控制对象生命周期。当最后一个拥有该对象的 shared_ptr 不存在时,该对象被自动销毁。因此,在上面的示例程序中,当 p2 超出范围时,引用计数减1,Foo 对象将被销毁。当 wp1 超出范围时,因为引用计数已经为0,所以 Foo 对象再次被销毁。

另外,C++还提供了一种名为“std::enable_shared_from_this”的模板类,它允许智能指针在对象的成员函数中获取对对象的共享所有权。

下面是一个使用std::enable_shared_from_this的示例程序:

 1 #include <iostream>  
 2 #include <memory>  
 3   
 4 struct Foo : std::enable_shared_from_this<Foo> {  
 5     void bar() {  
 6         std::cout << "Foo::bar\n";  
 7         auto sptr = shared_from_this();  
 8         if (sptr) {  
 9             sptr->baz();  
10         }  
11     }  
12     void baz() {  
13         std::cout << "Foo::baz\n";  
14     }  
15 };  
16   
17 int main() {  
18     std::shared_ptr<Foo> p1(new Foo); // 使用 shared_ptr 管理 Foo 对象的生命周期  
19     p1->bar(); // 在 bar() 中使用 enable_shared_from_this 获取对 Foo 对象的共享所有权,并调用 baz() 函数  
20     // p1 超出范围,引用计数减1,因为 enable_shared_from_this 不增加引用计数  
21     // Foo 对象被销毁  
22     return 0;  
23 }

在这个示例程序中,我们创建了一个 Foo 对象,使用 shared_ptr 管理它的生命周期,并在它的成员函数 bar() 中使用 enable_shared_from_this 获取对它的共享所有权。在 bar() 中,我们还调用了另一个成员函数 baz()。当 p1 超出范围时,引用计数减1,因为 enable_shared_from_this 不增加引用计数,所以 Foo 对象被销毁。当最后一个拥有该对象的 shared_ptr 不存在时,该对象被自动销毁。

另外,C++的智能指针还提供了一些功能,如“std::atomic_shared_ptr”和“std::shared_ptr_future”,可以让你在多线程环境中更安全地使用智能指针。这些功能可以帮助你避免多线程竞争条件等问题。

除此之外,C++还提供了一些更高级的模板库,如“Boost”和“Qt”,其中包含更多高级的智能指针和内存管理功能。例如,Boost库中的“boost::interprocess”库提供了跨进程内存管理和共享访问等功能。这些高级功能可以让你更加灵活地管理内存和开发大规模的应用程序。

总之,C++的智能指针是一个非常强大和灵活的内存管理工具。通过使用不同类型的智能指针和遵循RAII原则,你可以在C++程序中更安全、更有效地管理内存和其他资源。

标签:std,对象,C++,智能,shared,Foo,ptr,指针
From: https://www.cnblogs.com/Arthurian/p/17407347.html

相关文章

  • C++STL进阶:pb_ds库
    Windows,64bitG++(ISOc20)stack=268435456开启O2优化万能头文件CodeForces在\(\ttC^{20(64)}_{++}\)版本下无法使用bits;如果需要使用priority_queue则无法使用using(会和std撞名字)。#include<bits/extc.h>usingnamespace__gnu_pbds;优先队列(不常用)概述......
  • Python开发实例(二十一)智能家居控制器:模拟一个简单的智能家居控制系统,控制虚拟设备的状
    在这个实例中,我们将模拟一个简单的智能家居控制系统,通过Python代码来控制虚拟设备的状态。我们将使用一个字典来表示设备及其状态,并提供用户界面来操作这些设备。下面是一个智能家居控制器的Python程序:#初始化设备状态字典devices={'灯':'关闭','空调':'关闭',......
  • C++的异常类型与多级catch匹配
    try-catch的用法:try{//可能抛出异常的语句}catch(exceptionTypevariable){//处理异常的语句}我们还遗留下一个问题,就是catch关键字后边的exceptionTypevariable,这节就来详细分析一下。exceptionType是异常类型,它指明了当前的catch可以处理什么类型的异常;varia......
  • C++ 学习笔记、01 | 开发简单职工管理系统遇到的一些问题
    记录开发简单职工管理系统遇到的一些问题,黑马教程https://www.bilibili.com/video/BV1et411b73ZP147~P166头文件与源文件头文件只声明,源文件来实现(本质上是类内声明类外实现)源文件需要引用特定的头文件ifndefOOPFINAL_WORKER_H#defineOOPFINAL_WORKER_H#include<......
  • 合并果子题解-C++ STL priority_queue容器的使用
    说明:本博文关于priority_queue容器的说明来源于www.cnblogs.com/fusiwei/p/11823053.html本人是刚刚接触算法竞赛的萌新,如果有大佬发现了错误,还望指出(真的有人会看本蒟蒻的博文吗)这是我的第一篇博文,更多是作为测试以后会将博客作为笔记记录学习的体会基本概念priority_queu......
  • c++论文查重
    github连接这个作业属于哪个课程软件工程这个作业要求在哪里在这里这个作业的目标了解PSP,写一个论文查重程序,使用github管理项目PSP表PSP2.1PersonalSoftwareProcessStages预估耗时(分钟)实际耗时(分钟)Planning计划2020Estimate估计这个任......
  • C++20起支持的一个小特性
    注释掉的为传统的写法,从C++20起支持default关键字修饰的写法,即使是成员变量有多个的时候也支持,减轻了程序员的心智负担。......
  • C++ STL 编程指北
    C++STL编程指北未避免歧义,所有容器的swap方法和不常用方法均未写1.vector向量容器用一句话来说,vector就是可变长数组。但vector所支持的可变长特性,并不是在原空间之后接续新空间来实现的,因为无法保证之后尚有可供分配的空间。底层实现上当增加新元素时,如果当前vector容......
  • C++关于字符串的一些函数
    islower,isupper返回类型为int,当符合条件时返回非零值,并不一定是1,0tolower,toupper返回类型为int。isdigit判断一个字符是否是十进制数字,返回值:返回值为非零(真)表示c是十进制数字,返回值为零(假)表示c不是十进制数字。isalphaisalpha()用来判断一个字符是否为字母,如果是字符......
  • 《安富莱嵌入式周报》第308期:开源带软硬件安全认证的PLC设计,开源功率计,可靠PID实现,PR2
     视频版:https://www.bilibili.com/video/BV1F24y157QE1、ST发布安全认证版PLC设计套件https://www.st.com/en/evaluation-tools/steval-silplc01.html含原理图(新的手册里面把原理图撤掉了):steval-silplc01+(2).pdf(502.71KB)硬件方面的安全认证正进行中,满足SIL2等级。随机故障......