C/C++编程:对象生存期和资源管理(为什么要引入智能指针)

与托管语言不同C++ ,没有自动垃圾回收。 这是在程序运行时释放堆内存和其他资源的内部过程。 C++程序负责将所有获取的资源返回到操作系统。 未能释放未使用的资源称为 “泄漏”。 在进程退出之前,泄漏的资源对其他程序不可用。 具体而言,内存泄漏是 C 样式编程中出现 bug 的一个常见原因。

新式C++通过在堆栈上声明对象,尽可能避免使用堆内存。 如果资源对于堆栈而言太大,则它应归对象所有, 初始化对象时,它将获取其拥有的资源。然后,该对象负责在其析构函数中释放资源。所属对象本身在堆栈上声明。对象拥有的资源的原则也称为”资源采集初始化“或者RAII

当资源拥有的堆栈对象超出范围时,将自动调用其析构函数。也就是说,C++中的垃圾回收与对象生存期密切相关,并且是确定性的。资源始终在程序中的已知点释放,即可以对其进行控制。

下面演示一个w的简单对象。 它在函数作用域的堆栈上声明,并在函数块的末尾自动被销毁

class widget{
    
    
private:
      gadget g; //生存期自动绑定到封闭对象
public:
      void draw();
};


void functionUsingWidget(){
    
    
    widget w;   //生存期自动绑定到封闭范围
                //构造w,包括w.g成员
    
    w.draw();
}  // w和w.g自动销毁和解除分配 

w 拥有内存资源,因此必须在其析构函数中包含代码以删除内存。

class widget
{
    
    
private:
    int* data;
public:
    widget(const int size) {
    
     data = new int[size]; } // acquire
    ~widget() {
    
     delete[] data; } // release
    void do_something() {
    
    }
};

void functionUsingWidget() {
    
    
    widget w(1000000);   //生存期自动绑定到封闭范围
                         //构造w,包括w.g成员
    w.do_something();

} //自动调用构造函数,销毁释放w和w.data

自 c + + 11 起,有一种更好的方法来编写前面的示例:使用标准库中的智能指针。智能指针处理其拥有的内存分配和删除操作。使用智能指针,无需在widget类中使用显式析构函数

#include <memory>
class widget
{
    
    
private:
    std::unique_ptr<int> data;
public:
    widget(const int size) {
    
     data = std::make_unique<int>(size); }
    void do_something() {
    
    }
};

void functionUsingWidget() {
    
    
    widget w(1000000);    //生存期自动绑定到封闭范围
                          //构造w,包括w.g成员
    // ...
    w.do_something();
    // ...
}// w和w.g自动销毁和解除分配 

通过使用智能指针进行内存分配,可以消除内存泄漏的可能性。 此模型适用于其他资源,例如文件句柄或套接字。 你可以在类中以类似的方式管理自己的资源。

猜你喜欢

转载自blog.csdn.net/zhizhengguan/article/details/115344787