【问题标题】:Local variable and memory leak局部变量和内存泄漏
【发布时间】:2019-03-27 21:45:34
【问题描述】:

我正在阅读一些东西,并遇到了这个:

当变量超出范围时调用析构函数

所以我的问题是没有析构函数的变量会发生什么?

举个例子:

class A {
    public:
        A () { }
};

void foo () {
    A a;
}

int main (void) {
    foo();
}

所以在这种情况下是a()?分配给a 的内存在foo() 完成后是否被销毁?

比我有这个例子:

class A {
        std::vector <int> aa;
    public:
        A () : aa(5) { }
};

void foo () {
    A b;
}

int main (void) {
    foo();
}

在这种情况下,分配给b 的内存在foo() 完成后是否也被销毁?

再澄清一点,我知道:

class A {
    public:
        A () { }
};

等价于

class A {
    public:
        A () { }
        inline ~A() = default;
};

但我的问题是,当foo() 完成时是否调用了这个内联破坏?

编辑: inline 析构函数是什么时候添加的?

【问题讨论】:

  • A a(); -- 这不会创建对象。这声明了一个名为 a() 的函数,它不接受任何参数并返回一个 A 对象。
  • @Gox 在main() 中对 foo(); 的调用可能会被任何体面的 c++ 编译器优化掉,因为该函数没有任何效果。
  • 旁注:析构函数不会释放被销毁对象的内存。它最常被称为释放内存的链的一部分,但可以单独调用以在不释放内存的情况下销毁对象。有关更多信息,请参阅Placement new/delete

标签: c++ memory memory-leaks


【解决方案1】:

如果您不提供析构函数,编译器将为您提供一个。这个析构函数会调用任何成员变量和基类的析构函数。

在某些情况下,您必须编写析构函数以避免泄漏。一种情况是,如果您持有一个指向用new 分配的东西的裸指针,并且您的对象是“拥有”该指针的最佳人选。在大多数情况下,当您使用 new 分配某些东西时,您认为自己是指针的所有者。

另一种情况是当您获得某种其他类型的资源并需要释放它时。例如,如果您打开一个文件或套接字,您可能需要编写一个自定义析构函数来关闭它。

尽管如此,我对所有此类资源所做的是创建一个包装资源的类,并使用一个析构函数来关闭它。这使问题本地化,因此我必须尽可能少地记住我的大部分代码的资源管理。这是 C++ 中的一个常见习语,被称为RAII,意思是“资源获取即初始化”。

这也是为什么您应该更喜欢make_uniquemake_sharedvector 之类的东西而不是使用new 分配内存的原因。它们为您提供包装内存资源的对象,其析构函数会自动为您释放资源。

要更彻底地回答您对我的回答的评论中的问题...

当控制离开它被声明的块时,就会调用局部变量的析构函数。举个具体的例子:

void foo () {
    A b;
    {
        A c;
    } // Destructor for c is called here
} // Destructor for b is called here.

【讨论】:

  • @Gox - 是的,对于堆栈上的变量,析构函数在它声明的块退出时被调用。
  • @Gox - 我在对我的回答的评论中为您的问题添加了更完整的答案。而且,不客气。
【解决方案2】:

来自the standard

如果一个类没有用户声明的析构函数,析构函数被隐式声明为默认([dcl.fct.def])。隐式声明的析构函数是其类的 inline public 成员。

换句话说,

class A {
    public:
        A () { }
};

等价于

class A {
    public:
        A () { }
        inline ~A() = default;
};

至于你的问题

但我的问题是,当foo() 完成时,会调用这个内联破坏吗?

答案是肯定的。但是,即使对于用户定义的析构函数也是如此。

【讨论】:

  • @Gox,你想知道什么时候调用析构函数吗?
  • @Gox,谁在谈论此类对象的内存泄漏?
  • @Gox,我听到了你的沮丧。我希望你坚持语言。就像任何学到的技能一样,练习会变得更容易。祝你好运。
  • 你想知道什么时候调用析构函数吗? 是的。 谁在谈论此类对象的内存泄漏?一些旧的轻松学习 C++ 教程。有人建议我阅读该教程的印刷版。
  • @Gox,内联析构函数已经存在了很长时间。我从 1995 年就开始使用它。它肯定是 C++98 标准的一部分。
猜你喜欢
  • 2012-01-29
  • 2023-03-28
  • 2019-04-11
  • 2014-05-25
  • 2013-07-06
  • 1970-01-01
  • 2013-07-21
  • 2013-11-06
  • 1970-01-01
相关资源
最近更新 更多