当前位置: 首页 > news >正文

c++ 智能指针使用注意事项及解决方案

c++11智能指针

  • shared_ptr
    • 介绍
    • 注意事项
    • 示例
    • 解决方案
  • weak_ptr
    • 特点
    • 示例
  • unique_ptr
    • 特点
    • 示例

shared_ptr

介绍

shared_ptr 是一种智能指针,用于自动管理动态分配的对象的生命周期。它通过引用计数机制来确保当最后一个 shared_ptr 指向一个对象时,该对象会被自动销毁。

注意事项

当两个或多个 shared_ptr 实例相互引用时,会形成一个环形引用,导致引用计数永远不会达到零,从而引起内存泄漏。

示例

#include <memory>
#include <iostream>class B; // 前向声明class A {
public:std::shared_ptr<B> b_ptr;~A() {std::cout << "A destructor called" << std::endl;}
};class B {
public:std::shared_ptr<A> a_ptr;~B() {std::cout << "B destructor called" << std::endl;}
};int main() {std::shared_ptr<A> a = std::make_shared<A>();std::shared_ptr<B> b = std::make_shared<B>();a->b_ptr = b;b->a_ptr = a;return 0;
}

在这个例子中,A 的实例持有 B 的一个 shared_ptr,而 B 的实例也持有 A 的一个 shared_ptr。这导致它们的引用计数永远不会降到零,因此它们的析构函数永远不会被调用,从而造成内存泄漏。

解决方案

使用 std::weak_ptr
std::weak_ptr 是一种智能指针,它不会增加对象的引用计数。它设计用来解决 shared_ptr 的环形引用问题。你可以将其中一个对象的 shared_ptr 替换为 weak_ptr 来避免环形引用:

#include <memory>
#include <iostream>class B; // 前向声明class A {
public:std::weak_ptr<B> b_ptr; // 使用 weak_ptr 替代 shared_ptr~A() {std::cout << "A destructor called" << std::endl;}
};class B {
public:std::shared_ptr<A> a_ptr;~B() {std::cout << "B destructor called" << std::endl;}
};int main() {std::shared_ptr<A> a = std::make_shared<A>();std::shared_ptr<B> b = std::make_shared<B>();a->b_ptr = b;b->a_ptr = a;return 0;
}

在这个修改后的例子中,A 类使用 std::weak_ptr 来引用 B 类的实例。这样,A 对 B 的引用不会增加 B 的引用计数。因此,当 main 函数结束时,a 和 b 的引用计数都会降到零,它们所指向的对象将被正确销毁,从而避免了内存泄漏。

weak_ptr

weak_ptr 是一种智能指针,用于观察 std::shared_ptr 所管理的对象,但不拥有该对象。std::weak_ptr 不会增加对象的引用计数,因此不会影响对象的生命周期。它主要用于解决 std::shared_ptr 的环形引用问题。

特点

  • 不拥有对象,只是观察者。
  • 用于监视 std::shared_ptr,但不影响其引用计数。
  • 可以从 std::weak_ptr 创建 std::shared_ptr 来访问对象(如果对象还存在)。

示例

#include <iostream>
#include <memory>class Widget {
public:Widget() { std::cout << "Widget constructed\n"; }~Widget() { std::cout << "Widget destroyed\n"; }
};int main() {std::shared_ptr<Widget> sharedPtr = std::make_shared<Widget>();std::weak_ptr<Widget> weakPtr = sharedPtr;std::cout << "Shared count: " << sharedPtr.use_count() << std::endl; // 输出 1if (auto tempSharedPtr = weakPtr.lock()) { // 尝试从 weak_ptr 获取 shared_ptrstd::cout << "Object is alive\n";} else {std::cout << "Object is destroyed\n";}sharedPtr.reset(); // 释放 shared_ptr 所有权if (auto tempSharedPtr = weakPtr.lock()) { // 再次尝试获取std::cout << "Object is alive\n";} else {std::cout << "Object is destroyed\n"; // 此时输出}return 0;
}

unique_ptr

unique_ptr 是一种智能指针,它提供对单一对象的独占所有权。这意味着 std::unique_ptr 实例拥有它所指向的对象,并且不允许复制该智能指针,只允许移动。当 std::unique_ptr 被销毁时,它所指向的对象也会被自动销毁。

特点

  • 独占所有权模型。
  • 不支持复制,只支持移动。
  • 自动释放所拥有的资源。
  • 轻量级,开销小。

示例

#include <iostream>
#include <memory>class Widget {
public:Widget() { std::cout << "Widget constructed\n"; }~Widget() { std::cout << "Widget destroyed\n"; }
};int main() {std::unique_ptr<Widget> widgetPtr = std::make_unique<Widget>();// std::unique_ptr<Widget> anotherPtr = widgetPtr; // 编译错误,不能复制std::unique_ptr<Widget> movedPtr = std::move(widgetPtr); // 移动是允许的return 0;
}

相关文章:

  • 华为中小企业组网
  • Ai绘画行业又叒翻天了!Stable Diffusion 3.0开源!多图实测附安装包!
  • arsetryhtehrwgefwadasdadasd
  • 算法题解记录29+++全排列(百日筑基)
  • 学习笔记——路由网络基础——路由优先级(preference)
  • Docker从容器打包镜像到本地保存与加载
  • SpringTask-Timer实现定时任务
  • 使用 C# 进行面向对象编程:第 10 部分
  • 嵌入式中间件_1.嵌入式中间件的定义及特点
  • 机器学习python实践——数据“相关性“的一些补充性个人思考
  • NettyのEventLoopChannel
  • 超高清图像生成新SOTA!清华唐杰教授团队提出Inf-DiT:生成4096图像比UNet节省5倍内存。
  • 银行数仓项目实战(一)--什么是数据仓库
  • 独立游戏之路:Tap篇 -- Unity 集成 TapTap 广告详细步骤
  • MySQL触发器基本结构
  • Brief introduction of how to 'Call, Apply and Bind'
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • Mysql优化
  • PHP的类修饰符与访问修饰符
  • Solarized Scheme
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 聚类分析——Kmeans
  • 前端面试题总结
  • 深度学习中的信息论知识详解
  • 使用阿里云发布分布式网站,开发时候应该注意什么?
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • 智能网联汽车信息安全
  • ​批处理文件中的errorlevel用法
  • #Z0458. 树的中心2
  • $.each()与$(selector).each()
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (a /b)*c的值
  • (补充):java各种进制、原码、反码、补码和文本、图像、音频在计算机中的存储方式
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (算法)Travel Information Center
  • (一)SpringBoot3---尚硅谷总结
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • .Net Remoting(分离服务程序实现) - Part.3
  • .NET 使用 JustAssembly 比较两个不同版本程序集的 API 变化
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • [AHK] WinHttpRequest.5.1报错 0x80092004 找不到对象或属性
  • [bzoj1038][ZJOI2008]瞭望塔
  • [C#] 基于 yield 语句的迭代器逻辑懒执行
  • [C++]高精度 bign (重载运算符版本)
  • [CF407E]k-d-sequence
  • [ComfyUI进阶教程] animatediff视频提示词书写要点
  • [Contiki系列论文之2]WSN的自适应通信架构
  • [docker] Docker容器服务更新与发现之consul
  • [Editor]Unity Editor类常用方法
  • [Enterprise Library]调用Enterprise Library时出现的错误事件之关闭办法
  • [Everyday Mathematics]20150130