c++: 是否会自动delete?

一直以来对于C++内存管理部分存在一些小疑问,尤其是涉及到内存泄漏的知识,我觉得还是有必要提出来,以加深印象。


问题1:new了一块内存,一定要手动delete吗?什么时候系统会自动帮助我们delete?

回答:首先C++内存区域分为5个:

  • 全局区(静态区)
  • 常量区
  • 程序代码区

    不过我们使用的,一般都是栈、堆。比如以下这段代码:

#include <iostream>
#include <string>
using namespace std;


class Node {
public:
    Node(int id) {
        cout << "Constructor: " << id << endl;
        this->id = id;
    }

    ~Node() {
        cout << "Destructor: " << this->id << endl;
    }

private:
    int id;
};


int main() {
    Node node1(1);
    Node* node2 = new Node(2);

    // ...do something

    return 0;
}

需要说明的无非就是,node1是在栈上分配的,而node2则使用了堆内存。这里有个结论:对于栈上分配的变量、对象,程序结束的时候,由系统来回收内存;而堆上分配的内存,则需要程序员自行管理,最后一定要记得delete来显式释放堆内存。也就是说,new和delete一定要成对出现。

对于上面这个例子,输出结果是:

Constructor: 1
Constructor: 2
Destructor: 1

node2占用的堆内存没有得到delete,它的destructor也就没有调用。这样,内存泄漏就发生了,我们在Linux系统上可以使用Valgrind这个工具来检测c/c++程序的内存泄露,或者分析内存的使用情况。使用命令:

valgrind –tool=memcheck –leak-check=full ./out
Valgrind的检测结果

可以看到,在“defintely lost”这一行显示有4个byte的内存发生泄漏了,对应的就是一个Node(即node2)的大小。


问题2:Destructor的作用是什么?什么时候需要写destructor?

回答:简单来说,析构函数就是释放本对象占用的内存,避免内存泄漏的。一般来说,我们在析构函数中写代码,是为了在释放本对象之前,释放其成员变量所使用的堆内存。所以,有时候,析构函数的函数块内可以什么都不写,但有时候就必须写,具体看以下:
(1)当我们定义的类中的成员没有指针变量(及其申请的对象),比如用的都是基本类型:int、char等,或者已经完美封装的STL类型:string、vector、list的时候,可以不写析构函数。因为对于基本类型,是分配在栈上,程序结束后会自动回收;而对于STL类型,如string类,就算内部(给char数组)动态分配了堆内存,但是STL已经帮我们写好它的destructor了,在它的destructor中给char数组delete;而且,string对象是在栈上分配的。所以,程序结束后,系统会帮我们回收这个string对象。
(2)如果类成员中存在指针变量,在constructor或者别的成员函数中分配了内存,那么必须在destructor中delete。这样,系统在回收这个类的实例的内存时,才会完全把其引用的所有堆内存释放掉。

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/VitaLemon__/article/details/59110409
个人分类: c(++)基础知识
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭