【问题标题】:Templated Manual Destructor Call Not Working模板化手动析构函数调用不起作用
【发布时间】:2019-11-24 11:48:11
【问题描述】:

我想销毁模板化的对象,但保持分配的内存被填充。不幸的是,对象的析构函数永远不会被调用,并且单步执行代码,它会跳过手动调用。

#include <iostream>

template <typename type> class TestClass
{
    private:

        type *data;

    public:

        TestClass();
        ~TestClass();

        template <typename T> void Set(T &&element);
        void Replace();
};


template <typename type> TestClass<type>::TestClass()
{
    data = reinterpret_cast<type *>(new char[sizeof(type)]);;
}

template <typename type> TestClass<type>::~TestClass()
{
}

template <typename type> template <typename T> void TestClass<type>::Set(T &&element)
{
    new(data) type(static_cast<T &&>(element));
}

template <typename type> void TestClass<type>::Replace()
{
    type *pointer = reinterpret_cast<type *>(&data[0]);
    pointer->~type();

    //Fill with data
}

class MyClass
{
    public:

        MyClass()
        {
        }

        ~MyClass()
        {
            std::cout << "Called" << "\n";
        }
};

int main()
{
    MyClass *myClass = new MyClass();

    TestClass<MyClass *> myObject;

    myObject.Set(myClass);
    myObject.Replace();

    return 0;
}

我已经在 VS 2017 和在线 C++ 编译器上对此进行了测试。两者都跳过了指针->~type();当单步执行时,析构函数永远不会被调用。

编辑:重写代码,现在重现错误。

【问题讨论】:

  • 我们可以得到minimal reproducible example吗?
  • 我已经更新了代码以显示精简版本,但就能够编译它而言,恐怕需要做一些工作。

标签: c++ pointers templates destructor


【解决方案1】:

它确实调用了析构函数。

#include <iostream>

class Type
{
    public:
    ~Type()
    {
        std::cout<< __FUNCTION__ << "\n";
    }
};


template <typename type> class MyClass
{
    private:

        type *data;

    public:

        MyClass();
        ~MyClass(){}

        void Replace();
};


template <typename type> MyClass<type>::MyClass()
{
    data =  reinterpret_cast<type *>(new char[sizeof(type)]);;
}


template <typename type> void MyClass<type>::Replace()
{
    type *pointer = &data[0];
    pointer->~type();

    //Fill with replacement data
}
int main()
{

    MyClass<Type> myClass;

    std::cout <<"Before destruction\n";
myClass.Replace();
std::cout << "After destruction\n";
    return 0;

}

【讨论】:

  • 感谢您的回复。您的代码确实有效,因此我设法拼凑了一个在多个编译器上重现错误的示例。
【解决方案2】:

为了允许模板处理类型,C++ 允许obj.~type()ptr-&gt;~type() 语法,即使类型不是类类型(但不是数组类型)。含义与该类型的自动对象在其作用域结束时发生的任何事情相同:如果它是类类型,则调用析构函数,如果不是,则什么也不会发生。对于类型不是类类型的情况,这种语法称为pseudo-destructor

现在查看您的示例,您正在使用类模板专业化TestClass&lt;MyClass*&gt;。所以在TestClass&lt;type&gt;::Replace()的成员定义的实例化中,typeMyClass*的别名。声明

type *pointer = reinterpret_cast<type *>(&data[0]);

定义了一个type* 类型的变量,即MyClass**。 (右侧令人困惑:&amp;data[0]data 相同,假设它指向某个东西,并且两个表达式都已经具有 type* 类型。)

声明

pointer->~type();

说要销毁pointer 指向的type 类型的对象。也就是说,它说要销毁MyClass* 类型的对象,即*pointerMyClass* 不是类类型;它是一种指针类型。所以这是对伪析构函数的调用,绝对没有任何反应。

没有足够的上下文来确定如何解决此问题,但也许您需要使用TestClass&lt;MyClass&gt; 而不是TestClass&lt;MyClass*&gt;? (另外,在实际代码中不要忘记五规则/三规则。)

【讨论】:

  • 这很有意义,也解释了很多。非常感谢。
猜你喜欢
  • 2021-04-24
  • 2014-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-28
  • 2018-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多