【问题标题】:How to call destructor of type in template?如何在模板中调用类型的析构函数?
【发布时间】:2012-10-24 00:41:09
【问题描述】:

例如,我们有一个这样的函数:

template <typename TYPE>
void construct_and_destruct(TYPE & object)
{
    //...
}

我们不能调用构造函数和析构函数,例如 object.Type()object.~Type()(现在不是真的)(为什么?=C

要调用构造函数,我们可以点赞new(&amp;object) TYPE()。而且我不知道如何调用析构函数(不存在位置delete)。如何做到这一点?

【问题讨论】:

  • 您应该将您感兴趣的代码从 dtor 拆分为单独的成员函数,然后调用它。

标签: c++ templates constructor destructor template-function


【解决方案1】:

你可以调用析构函数:

object.~TYPE();

但它可能不是您想要的,并且可能会被双重删除。

构造函数很简单:

object = TYPE();

【讨论】:

  • 你是对的,但是object = TYPE(); 执行额外的operator =。相反,这更好地使用placement new(使用奇怪的语法=))。
  • @4Bytes: 不。只是不要这样做object.~TYPE(); new (object) TYPE(); 使用object = TYPE(); 清洁得多@ 让系统自行清理。
  • @David 这是不正确的:您正在做作业。 TYPE 必须在其赋值运算符中假设其构造函数之一先前已被调用。你将违反这一点。
  • @JohannesSchaub-litb - 我假设 4Bytes 想要将最初声明为 TYPE object 的对象“重置”为某种原始状态,并且通过 new (&amp;object) TYPE(&lt;some argument list&gt;); 这样做。在这里只使用placement new 有一个问题:那个placement new 会导致object 中分配的资源泄漏。解决方案:在重建之前破坏object。这就是为什么我认为 h4Bytes 正在询问显式调用析构函数的原因。除了对析构函数的错综复杂的调用,然后是新的放置,还有一个更好的方法来完成他想要的。
  • @JohannesSchaub-litb - 我在五个小时前写new (object) TYPE() 时的评论中有一个错误。这当然是非法的; Placement new 的参数应该是一个指针。我的意思是new (&amp;object) TYPE()——或者可能不是默认构造函数。
【解决方案2】:

object.~TYPE()object.~TYPE::TYPE() 我认为都是正确的。听起来有点可疑,但是你想达到什么目的?

【讨论】:

  • 不,object.~TYPE() 不正确。我知道construct_and_destruct是没用的函数,但我写这个是为了example
  • object.~TYPE() 是正确的。也就是说,你为什么要调用析构函数?
  • @David Hammen,对不起,我错了。析构函数也是如此。它是执行我的任务所必需的。
  • @DavidHammen 如果你有一个联合类型,并且有一些变量来描述它是哪种类型,你需要在你自己的析构函数中调用正确的析构函数。
  • @DavidHammen:另外,如果你分配了一个自定义的new 运算符,你不能调用标准的delete,但你需要调用你自己的。
【解决方案3】:

试试这个Calling destructor with decltype and\or std::remove_reference,它对我来说可以调用非限定类型的析构函数(模板参数中未指定的内部类)...

【讨论】:

    【解决方案4】:

    我遇到了一个稍微不同的问题,但也适用于placement-new/delete,解决方案应该类似。

    给定一个依赖类型名称,新的展示位置:

    new (&foo) typename AT::T(arg, arg, arg);
    

    相关的删除很棘手:

    foo.~ typename AT::T();  // Doesn't work, nor do variations of syntax
    

    现代解决方案似乎是std::destroy_at(&amp;foo),但我的编译器没有完整的 C++17。不过,推出自己的基本版本并不难:

    template <typename T>
    constexpr void destroy_at(T* p)
    {
      p->~T();
    }
    

    看起来不错。

    【讨论】:

      猜你喜欢
      • 2012-07-24
      • 2020-07-21
      • 2020-04-15
      • 2023-03-23
      • 1970-01-01
      • 2017-09-12
      • 2014-09-23
      • 2020-09-10
      • 1970-01-01
      相关资源
      最近更新 更多