【问题标题】:When exactly destructor of a class invoked in C++?何时在 C++ 中调用类的析构函数?
【发布时间】:2015-08-22 19:52:43
【问题描述】:

我是 C++ 新手。我写了下面的代码来理解构造函数和析构函数在 C++ 中是如何工作的。

#include<iostream>

using namespace std;

class Line
{
    private:
        Line();
    public:
        int length;
        static void getInstance(Line* objLine);
        ~Line();
};

void Line::getInstance(Line* objLine)
{
    if(objLine == NULL)
    {
        objLine = new Line();
    }
}

Line::Line()
{
    cout<<"In the Constructor"<<endl;
}

Line::~Line()
{
    cout<<"In the Destructor"<<endl;
}

int main()
{
    Line* objLine = NULL;
    Line::getInstance(objLine);
    return 0;
}

我读过当对象超出范围时调用类的析构函数。在上面的代码中,对象由局部变量 objLine 处理。所以在主要的结束时,我预计会调用析构函数。但它永远不会被调用。任何人请告诉我在上述情况下何时调用析构函数

【问题讨论】:

  • objLinemain 结束时超出范围,但objLine 不是 Line 的实例,它只是一个指针。因此,main 末尾的指针超出范围。它没有析构函数。如果您改为编写 Line objLine,则析构函数将在 objLine 超出范围时执行。
  • 对于超出教育范围的软件,我建议使用共享指针,当变量超出范围时,它会调用析构函数。

标签: c++ c++11


【解决方案1】:

在 C++ 中,当变量超出范围时,或在使用 new 创建的对象上调用 delete 时,将调用析构函数。

您使用new 创建对象,但从不使用delete,因此从不调用析构函数。

如果你的代码是这样的:

int main() {
   Line objLine;
}

析构函数被调用。

【讨论】:

    【解决方案2】:

    这种情况你需要自己清理内存

    int main()
    {
        Line* objLine = NULL;
        Line::getInstance(objLine);
        delete objLine;
        return 0;
    }
    

    这是因为你使用了new 来分配内存,所以它在超出范围后不会自动清理。你需要使用delete清理内存

    正如@StefanoSanfilippo 提到的,您还需要将您的getInstance 函数更改为

    void Line::getInstance(Line*& objLine)
    

    【讨论】:

    • 其实这样不行。 objLine 按值传递给 getInstance ,它没有被修改,因此 delete objLine 实际上是对 delete NULL 的调用,这会导致无操作。
    【解决方案3】:

    范围规则对自动分配(即局部变量)有效。相反,您正在使用 new 运算符动态分配 Line 的实例:

    void Line::getInstance(Line* objLine)
    {
        if(objLine == NULL)
        {
            objLine = new Line();
        }
    }
    

    动态分配的对象未绑定到范围,必须使用delete 运算符显式删除。此外,上面的方法是内存泄漏:一旦你离开函数,你将失去对新创建对象的任何引用,因此你将无法访问或delete它。您需要实际修改传递给您的指针,例如通过如下修改您的代码:

    void Line::getInstance(Line** objLine)
    {
        if(objLine == NULL)
        {
            *objLine = new Line();
        }
    }
    

    此时你可以像这样使用它:

    int main()
    {
        Line* objLine = NULL;
        Line::getInstance(&objLine);
        // do something...
        delete objLine;
        return 0;
    }
    

    【讨论】:

    • The scope rule is valid for static allocation 实际上,静态分配的对象不会在作用域结束时被销毁。它们在main 返回后被销毁。您可能是指自动(堆栈)分配。
    • @user2079303 我的意思是 static(在编译时)而不是 dynamic(在运行时),但是是的,自动 更正确,我已经相应地编辑了帖子。我认为“自动存储”对于新手来说可能听起来有点奇怪。
    猜你喜欢
    • 2014-04-22
    • 1970-01-01
    • 2021-05-18
    • 2016-10-28
    • 2020-04-10
    • 2019-11-09
    • 2018-09-01
    • 1970-01-01
    • 2016-11-10
    相关资源
    最近更新 更多