模板化手动析构函数调用不起作用
Templated Manual Destructor Call Not Working
我想销毁模板对象,但要保留分配的内存。不幸的是,对象的析构函数从未被调用过,单步执行代码,它跳过了手动调用。
#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++ 编译器上对此进行了测试。两者都跳过了 pointer->~type();单步执行时永远不会调用析构函数。
编辑:重写了现在重现错误的代码。
确实会调用析构函数。
#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;
}
为了允许模板处理类型,C++ 允许使用 obj.~type()
或 ptr->~type()
语法,即使类型不是 class 类型(但不适用于数组类型) .其含义与该类型的自动对象在其作用域末尾发生的任何事情相同:如果它是 class 类型,则调用析构函数,否则,什么也不会发生。对于类型不是 class 类型的情况,此语法称为 pseudo-destructor.
现在查看您的示例,您正在使用 class 模板专业化 TestClass<MyClass*>
。所以在TestClass<type>::Replace()
的成员定义实例化中,type
是MyClass*
的别名。声明
type *pointer = reinterpret_cast<type *>(&data[0]);
定义了一个type*
类型的变量,即MyClass**
。 (right-hand 的一面令人困惑:&data[0]
与 data
相同,假设它指向某个东西,并且两个表达式都已经具有类型 type*
。)
声明
pointer->~type();
表示销毁 pointer
指向的 type
类型的对象。也就是说,它说要销毁 MyClass*
类型的对象,即 *pointer
。 MyClass*
不是 class 类型;它是一个指针类型。所以这是对 pseudo-destructor 的调用,但绝对没有任何反应。
没有足够的上下文来确定如何解决这个问题,但也许您需要使用 TestClass<MyClass>
而不是 TestClass<MyClass*>
? (此外,在实际代码中不要忘记 Five/Rule 三的规则。)
我想销毁模板对象,但要保留分配的内存。不幸的是,对象的析构函数从未被调用过,单步执行代码,它跳过了手动调用。
#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++ 编译器上对此进行了测试。两者都跳过了 pointer->~type();单步执行时永远不会调用析构函数。
编辑:重写了现在重现错误的代码。
确实会调用析构函数。
#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;
}
为了允许模板处理类型,C++ 允许使用 obj.~type()
或 ptr->~type()
语法,即使类型不是 class 类型(但不适用于数组类型) .其含义与该类型的自动对象在其作用域末尾发生的任何事情相同:如果它是 class 类型,则调用析构函数,否则,什么也不会发生。对于类型不是 class 类型的情况,此语法称为 pseudo-destructor.
现在查看您的示例,您正在使用 class 模板专业化 TestClass<MyClass*>
。所以在TestClass<type>::Replace()
的成员定义实例化中,type
是MyClass*
的别名。声明
type *pointer = reinterpret_cast<type *>(&data[0]);
定义了一个type*
类型的变量,即MyClass**
。 (right-hand 的一面令人困惑:&data[0]
与 data
相同,假设它指向某个东西,并且两个表达式都已经具有类型 type*
。)
声明
pointer->~type();
表示销毁 pointer
指向的 type
类型的对象。也就是说,它说要销毁 MyClass*
类型的对象,即 *pointer
。 MyClass*
不是 class 类型;它是一个指针类型。所以这是对 pseudo-destructor 的调用,但绝对没有任何反应。
没有足够的上下文来确定如何解决这个问题,但也许您需要使用 TestClass<MyClass>
而不是 TestClass<MyClass*>
? (此外,在实际代码中不要忘记 Five/Rule 三的规则。)