【问题标题】:Is there a way to get C++ destructors called eagerly?有没有办法让 C++ 析构函数被热切地调用?
【发布时间】:2016-12-31 13:59:49
【问题描述】:

我的 C++ 代码中的一些函数具有使用大量堆内存的临时本地对象。所以我希望它们在我处理完它们后立即被破坏并释放它们的记忆。但是 C++ 只有在变量名超出范围时才调用析构函数。有没有办法让编译器在变量的活动范围结束时自动调用析构函数或其他清理方法?

当然,我可以手动新建/删除对象,但这很不方便并且容易出错。同样令人不满意的是使用额外的大括号来明确限制范围。

编辑:从响应来看,当前的 C++ 功能似乎无法做到这一点。我会为下一个标准推荐它。

【问题讨论】:

  • 听起来你的函数太长了。
  • “同样不令人满意的是使用额外的大括号来明确限制范围”。学会爱上这种技术。
  • 我也不明白使用 new/delete 与使用额外大括号的最后一部分。那不是替代方案,因为要么对象是在堆上分配的,那么您必须使用 new/delete 并且添加大括号根本无济于事。或者它在堆栈上然后它是相反的方式......
  • @fgrdn RAII 无济于事,而且“全局管理器,它将清理长时间不使用的对象”通常听起来是个非常糟糕的主意。
  • 析构函数已经尽可能地“渴望”了。听起来你只是在编写糟糕的代码。为什么不在 Code Review 上发布呢?

标签: c++ optimization scope destructor


【解决方案1】:

你可以使用内部作用域,但通常表明你可以使用子函数

void foo()
{

    // some stuff
    {
        BigData bigData;

        // some other stuff
    } // bigData is released now.

    // some other stuff
}

这不处理交错变量。

【讨论】:

  • “同样不令人满意的是使用额外的大括号来明确限制范围。” OP 不想要大括号(但他们可能不得不处理它们:-))
  • @AndyG:同样令人不满意的是 OP 无缘无故编造的无意义限制。
  • @KerreSB 同意,但“更平等”听起来太有趣了 ;)
  • @KerrekSB 这不是一个毫无意义的约束。编译器为寄存器分配目的执行活性分析,因为程序员显然不希望必须通过范围手动指示变量活性的约束。那么为什么通过在本地对象的生存范围结束时自动调用析构函数来将其从寄存器(和堆栈内存)扩展到堆内存是不合理的呢?
  • @NicolasCapens:想想lock_guard 变量,它在定义后没有明确使用,但应该一直保留到作用域结束。
【解决方案2】:

不,根据定义,析构函数仅作为对象销毁序列的一部分被调用。

但是,没有什么能阻止您在不等待析构函数的情况下释放和释放您的类所拥有的任何资源。

例如,如果您的类有一个大的 std::list 类成员,则没有法律禁止您调用 clear() 来删除其内容,而无需等待其在析构函数中自然发生。

或者,如果你的类析构函数是“安全的”,并且做了需要做的事情,只需将它分解为一个私有类方法,让析构函数只包含私有方法调用,并且只要你做同样的事情想要释放相同的资源。

【讨论】:

    【解决方案3】:

    如果努力真的值得(至少测量两次!),您可以使用std::optional 让您能够更快地销毁选定的类类型。

    请确保您无法使用范围界定来实现目标。

    【讨论】:

    • 它如何在最后一次使用时自动销毁对象?
    • @NicolasCapens:没有办法在最后使用时自动销毁它,特别是因为对象的存在可能是重要的事情(例如考虑锁定或信号程序状态)。这只是可能的最接近的事情,允许您更早地创建/销毁并确保仍然正确管理生命周期。
    【解决方案4】:

    控制对象生命周期的一种方法是使用std::optional。这将允许对象提前结束其生命周期,但该过程不是自动的。这需要手动将变量设置为nullopt

    要获得您希望的自动行为,您可以为 std::optional 定义一个类型别名

    template <typename T>
    using eagerly_destroy = optional<T>;
    

    接下来,您将需要创建一个程序来处理您的源代码,以查找使用此 eagery_destroy 模板声明的所有变量,并找到这些变量的最后一次使用,并将 = nullopt 添加到正确的位置。

    或者您可以找到一个开源编译器实现并将其用作实现您建议的功能的起点。

    【讨论】:

      猜你喜欢
      • 2017-11-18
      • 2011-11-23
      • 2015-12-23
      • 1970-01-01
      • 2014-10-29
      • 1970-01-01
      • 2012-09-17
      • 2019-10-05
      • 1970-01-01
      相关资源
      最近更新 更多