Effective C++条款13:用一个类管理内存

  • 一般的new/delete操作--不利于扩展,维护

//参照书本的new/delete操作示例
class Investment {};


void f()
{
    Investment* pInv = new Investment();
    //...
    delete pInv;
}

这么做不会有问题,但不好,如果在//...处会return,或者其他操作导致未执行delete pInv;操作,会造成memory leak,这就引出了此条款,通过一个类去管理这new/delete操作。

  • 由于上述问题,我们希望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
上一篇:C++ std::lock_guard和std::unique_lock


下一篇:动态规划(Dynamic Programming)例题2 LeetCode62 Unique Paths