计算机
c base
c++ 基础 作用域及生命周期
c++ template
c++ 内存视角
c++ 函数指针
c++ 基础 基础语法
c++ 多线程
c++ 性能
c++ 类 基础
c++ 类 对象模型 类析构
c++ 类 设计模式
cmake
CMAKE环境搭建 windows
创建第一个cmakelists.txt
构建稍复杂的项目
动态链接库
EX1
EX1 START
EX1 ANSWER
EX2
EX2 START
EX2 ANSWER
EX3
EX3 START
EX3 ANSWER
变量
控制流程
函数和宏
查找和使用外部库
生成器表达式
qt 开发环境
qt c++
理解QObject 1
理解QObject 4
qt index
qt qml quick
qt ui
qt 多线程
数据结构 数组
PC问题监控及排查
PC程序性能优化
OS
TOOL
C++ STL
编程漫谈
C++实战-生产者 消费者流水线
C++实战 IO
本站点使用 MrDoc 构建
-
+
c++ 内存视角
# 动态内存管理 生命周期管理最佳实践 ```c++ 优先使用栈对象和智能指针 对于资源管理类,遵循RAII原则 明确所有权语义: 独占所有权:unique\_ptr 共享所有权:shared\_ptr 无所有权:原始指针或引用 在多线程环境中特别注意共享对象的生命周期 使用移动语义优化资源转移 避免从构造函数中泄漏资源 考虑使用工厂函数返回智能指针 ``` # 内存管理 1 优先使用栈对象 2 为必须使用new的情况编写RAII包装器 ``` 对象创建时机: 堆 & 栈\\ 栈:适用于生命周期明确,作用域内使用\\ 堆:适用于需要动态生命周期管理的对象\\ 线程安全创建对象\\ 单例模式与工厂模式\\ 初始化与延迟初始化\\ 异常安全与资源管理(RAII 智能指针shared\_ptr weak\_ptr)\\ 初始化、销毁\\ Qt父子机制\\ QObject //继承自QObject的类,建议用父子关系管理内存\\ 结合QThread使用 ``` ## 栈分配 ```c++ void MyClass::showMessage() { QMessageBox msgBox; // 栈上创建,自动释放 msgBox.setText("Hello"); msgBox.exec(); } ``` ## 堆分配+指定parent // 在类成员中 ```c++ MainWindow::MainWindow(QWidget \*parent) : QMainWindow(parent) { m\_button \= new QPushButton("Save", this); // this 作为 parent m\_label \= new QLabel("Status", this); } ``` ## 智能指针组合 // 使用 QSharedPointer 管理无 parent 的对象 ```c++ QSharedPointer<QFile> file = QSharedPointer<QFile\>::create("data.txt"); ``` // 或者使用 std::unique\_ptr ```c++ std::unique\_ptr<QTimer\> timer(new QTimer()); ``` C++ 里可能出现的内存问题大致有这么几个方面: ```c++ 1. 缓冲区溢出(buffer overrun)。 2. 空悬指针/野指针。 3. 重复释放(double delete)。 4. 内存泄漏(memory leak)。 5. 不配对的 new\[\]/delete。 6. 内存碎片(memory fragmentation)。 ``` ```c++ 1. 缓冲区溢出:用 std::vector<char\>/std::string 或自己编写 Buffer class 来管理缓冲区,自动记住用缓冲区的长度,并通过成员函数而不是裸指针来修改缓冲区。 2. 空悬指针/野指针:用 shared\_ptr/weak\_ptr,这正是本章的主题。 3. 重复释放:用 scoped\_ptr,只在对象析构的时候释放一次。 4. 内存泄漏:用 scoped\_ptr,对象析构的时候自动释放内存。 5. 不配对的 new\[\]/delete:把 new\[\] 统统替换为 std::vector/scoped\_array(unique\_ptr)。 6. 内存碎片:暂时不需要处理 ``` # 指针 ```c++ shared\_ptr //共享所有权 ,引入计数 使用场景: 普通对象分配 对象共享所有权 作为类成员 make\_shared //宏,不需要new,用一个控制块连接shared\_ptr ``` ```c++ 1 直接使用new + shared\_ptr构造函数 std::shared\_ptr<MyClass\> ptr(new MyClass()); // 这里确实调用了new;;控制块和对象内存一起分配,共有两次分配;会有内存泄漏问题(如果shared\_ptr初始化失败,之前new的内存将不会被释放) VS xx = new class(); shared\_ptr(xx) //和上一种写法比,多了双重释放风险 2 使用std::make\_shared auto ptr = std::make\_shared<MyClass\>(); 3 从已有的shared\_ptr创建 auto ptr2 = ptr //auto 自动类型推导 auto ptr3(ptr) 4 从weak\_ptr升级 std::weak\_ptr<MyClass> weak = ptr; auto ptr4 = weak.lock ``` 一个类多个实例\\ 多个指针共享一个对象所有权\\ 管理动态数组 结论:\\ 优先使用make\_shared;只有在需要自定义删除器或者特殊内存时才直接用new;避免混合使用new和shared\_ptr的裸指针构造函数\\ 自定义删除:文件句柄需要特殊关闭方式;数组需要delete\[\]\\ 需要自定义内存分配方式:aligned\_alloc分配对齐内存\\ 需要延迟初始化\\ 需要共享同一个对象的多个不同指针\\ 需要避免make\_shared的内存捆绑 ```c++ make\_shared 会将对象和控制块分配在连续内存中,这意味着即使所有 shared\_ptr 都释放了,如果还有 weak\_ptr 存在,对象占用的内存可能不会立即释放(因为控制块需要保留) make\_shared 不支持自定义删除器,如果需要自定义删除器,必须直接使用 shared\_ptr 构造函数 weak\_ptr 不能直接解引用,必须先用 lock() 方法转换为 shared\_ptr unique\_ptr //独占所有权 weak\_ptr //观察而不拥有 scope\_ptr //作用域结束时自动释放所管理的对象 ``` # RAII vs 智能指针 特性 自定义 RAII 类 智能指针\\ 资源释放逻辑 完全自定义 固定为 delete/deleter\\ 多资源管理 单类管理多个资源 每个指针管理一个资源\\ 移动语义支持 可自定义 自动提供\\ 线程安全性 自行实现 内置支持(shared\_ptr)\\ 开发效率 需要更多代码 快速简单\\ 性能开销 可优化到最小 有引用计数开销\\ 适用场景 复杂资源管理 简单内存管理
peipeo
2026年5月5日 11:08
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码