【问题标题】:Is the destructor of the local variable always guaranteed to be called when it goes out of scope?局部变量的析构函数是否总是保证在超出范围时被调用?
【发布时间】:2013-04-22 08:14:54
【问题描述】:

编译器可以进行很多优化(比如内联一些函数),我有点怀疑在我的程序中调用函数后并非所有分配给局部变量的内存都被清除(基于 OS X 的系统监视器),这就是我要问的原因:标准是否保证局部变量的所有析构函数都会在它们超出范围时被准确地调用?

【问题讨论】:

  • “清除”我假设您的意思是 已发布 回到运行时。是的,析构函数将被解雇。你在这些析构函数中做什么是任何人都猜到的。
  • 当你说“内存分配”时,如果它是由构造函数分配并由析构函数释放,那么分配的内存将被释放。
  • 你可以稍微怀疑一下,但我很确定这样的错误会在很早的阶段就被发现,早在编译器发布之前。

标签: c++ memory-management destructor


【解决方案1】:

是的。根据 C++11 标准的第 3.7.3 段:

显式声明register 或未显式声明staticextern 的块范围变量具有自动 存储期限这些实体的存储将持续到创建它们的块 退出

但是请注意,这涉及具有自动存储持续时间的变量。如果您使用 new 动态创建对象并将结果分配给本地原始指针,则 只有原始指针 将被销毁,而不是指向的对象:

{
    int* foo = new int(42);
} // Here you have a memory leak: the foo pointer is destroyed,
  // but not the object foo pointed to

【讨论】:

  • 非常重要的例子。感谢分享。
【解决方案2】:

是的,这是有保证的。

使用系统监视器监视内存使用可能并不精确,因为应用程序不会将内存返回给系统。一旦分配,它就属于应用程序,即使您的对象被销毁,您也可能看不到任何区别。

如果您想保证您的应用程序没有内存泄漏,您可能需要使用 valgrind 或 google 的 drMemory 或其他几个工具(google 用于“内存泄漏检测”)。在这种情况下,您将获得有关分配、解除分配、泄漏、内存访问违规等最精确的信息。

【讨论】:

  • 这就解释了为什么我在系统监视器中看不到足够的可用内存!有没有办法将未使用的内存返回给操作系统,或者它由操作系统内存管理专门处理?我将解释我的情况:我的程序多次调用了一个非常繁重的函数(它为内部使用分配了大量内存),并且它的内存占用量不会随着一次调用而增加,但它也不会下降那些调用(至少在系统监视器中)。
  • @lizarisk:我相信你无法将内存归还给系统。真的,试试 valgrind 或其他内存泄漏检测器。它会告诉你内存泄漏的确切位置。
【解决方案3】:

是的,保证每个超出范围的变量都会调用它的析构函数。

6.7 声明声明

2 具有自动存储持续时间 (3.7.3) 的变量在每次声明语句为 执行。 在块中声明的具有自动存储持续时间的变量在退出时被销毁 阻止 (6.6)。

【讨论】:

    【解决方案4】:

    是的,这总是会发生的。它由 C++ 保证。来自C++ FAQ lite

    [11.5] 我应该在局部变量上显式调用析构函数吗?

    不!

    析构函数将在创建本地块的块的 close } 处再次调用。这是语言的保证;它自动发生;没有办法阻止它发生。但是第二次在同一个对象上调用析构函数会得到非常糟糕的结果!砰!你死定了!


    这超出了你的问题,但基础是一样的。

    【讨论】:

      【解决方案5】:

      如果你有这样的代码:

      void f()
      {
        A a;  // create a local instance of A
              // memory will be allocated on the stack, 
              // and the constructor for `a` will be called.
      
        // various code here
      
        // here at the end of the scope, 
        // the destructor for `a` will be called,
        // and the memory on the stack will be freed.
      }
      

      【讨论】:

        猜你喜欢
        • 2016-09-26
        • 1970-01-01
        • 2013-10-20
        • 1970-01-01
        • 2013-09-23
        • 1970-01-01
        相关资源
        最近更新 更多