-
一般的new/delete操作--不利于扩展,维护
//参照书本的new/delete操作示例 class Investment {}; void f() { Investment* pInv = new Investment(); //... delete pInv; }
这么做不会有问题,但不好,如果在//...处会return,或者其他操作导致未执行delete pInv;操作,会造成memory leak,这就引出了此条款,通过一个类去管理这new/delete操作。
-
通过智能指针unique_ptr控制内存的释放(书上是auto_ptr,现被unique_ptr替代) 参考:shared_ptr和unique_ptr_zion--6135的博客-CSDN博客
- 由于上述问题,我们希望pInv在f()函数出当前作用域后可以回收内存,于是可以用unique_ptr
- 也就是把f()函数改为这样:unique_ptr即可在出当前作用域的时候调用delete,回收掉new出来的内存。
void f() { Investment *tmp = new Investment; std::cout << "==========" << (tmp) << std::endl; std::unique_ptr<Investment> pInv(tmp); //也就是用一个unique_ptr类管理new出来的对象 }
- 完整代码
#include <iostream> #include <memory> class Investment { private: /* data */ public: Investment(/* args */); ~Investment(); }; Investment::Investment(/* args */) { std::cout << "==========" << (this) << std::endl; } Investment::~Investment() { std::cout << "==========" << (this) << std::endl; } void f() { { Investment *tmp = new Investment; std::cout << "==========" << (tmp) << std::endl; std::unique_ptr<Investment> pInv(tmp); } std::cout << "================\n"; } int main() { { f(); } std::cout << "get wait\n"; std::cin.get(); }
- 通过智能指针shared_ptr控制内存的释放
和上述代码一样,不过需要把f()改为如下:
void f() { std::shared_ptr<Investment> pInv2; { std::shared_ptr<Investment> pInv(new Investment); //不用手工delete pInv2 = pInv; std::cout << "================" << pInv2.use_count() << std::endl; } std::cout << "================" << pInv2.use_count() << std::endl; }
根据打印日志:
Investment0x55573cad0eb0
================2
================1
~Investment0x55573cad0eb0
get wait可知:在f()函数退出的时候会调用对象的析构函数。因为此时use_count == 0
-
RAII机制
- unique_ptr和shared_ptr本质上是用了一种RAII的思想:通过一个类的构造与析构函数管理内存,unique_ptr和shared_ptr是这种思想的具体实现。
构造函数:传入new出来的对象作为这个类的初始值
析构函数:将传入的new对象delete掉.
下面这个例子:用memManager作为管理类,利用局部变量的特性让传入的new的对象在构造函数中保存new 出来的对象,在析构函数去delete掉这片内存。
#include <iostream> #include <memory> class memManager { public: memManager(int* aab) { int_ptr = aab; std::cout << "new " << int_ptr <<std::endl; } void printfx() { std::cout << "printfx" << std::endl; } ~memManager() { delete int_ptr; std::cout << "delete " << int_ptr <<std::endl; } private: int* int_ptr; }; int main() { { std::cout << "================\n"; memManager aaa = memManager(new int); aaa.printfx(); std::cout << "================\n"; } std::cout << "get wait\n"; std::cin.get(); }
这样可以不用担心后续的内存释放问题。
- 总结:(1)通过RAII对象来管理对象内存 (2)RAII的具体实现例子:shared_ptr和unique_ptr