删除模板类型
Deleting a Template Type
我有一个泛型类,看起来像这样:
template <class T>
class Example
{
private:
T data;
public:
Example(): data(T())
Example(T typeData): data(typeData)
~Example()
// ...
};
我对如何为这样的事情实现解构器有点困惑。具体来说,由于T
是任何类型的,它可以是在堆栈上分配的内存(通过无参数构造函数创建的Example
总是如此)或堆上分配的内存。
例如,如果客户端将 T
的类型设为int*
并提供指向动态内存的指针,我怎么知道在data
上调用delete
,而不是客户端是否将类型设置为 int
?
最简单的答案是:不要。不要试图对用户进行事后猜测并做一些他们可能意想不到的事情。采用与标准容器相同的策略:假设T
正确清理自身。
如果客户端代码编写正确,它将使用 RAII 类(如智能指针)自动和正确管理内存和其他资源。如果不是,则不能希望在提供程序代码中解决此问题。
让您的班级与std::unique_ptr
和std::shared_ptr
以及任何其他自定义 RAII 类一起工作,并让您的客户自己进行管理。毕竟,如果他们想存储非拥有的指针怎么办?
您可以使用模板专业化。
template <class T>
class Example
{
private:
T data;
public:
Example()
: data(T())
{}
Example(T typeData): data(typeData)
{}
};
template <class T>
class Example<T*>
{
private:
T* data;
public:
Example() : data(nullptr){}
Example(T* typeData): data(typeData) {}
~Example()
{
delete data;
}
};
int main()
{
Example<int> e;
Example<int*> e2;
return 0;
}
您不必像标准库那样担心它。 例如,如果您创建了一个指针向量,则负责在让该向量超出范围之前删除它们。 然后,人们可以决定是否要删除它(也许它是临时的排序,而其他东西拥有该对象)。 他们还可以使用智能指针,以便矢量通过智能指针的析构函数销毁对象。
在这种情况下,少即是多。 您不必做任何复杂的事情。 您不必维护模板的多个版本。 最后,模板的用户拥有更多控制权...当然还有责任。
使用可按类型选择的内存释放帮助程序模板类。您无需使用模板专业化对您的类进行配音。您只能编写一个类。
#include <type_traits>
template<typename T> // primary template
struct Releaser
{
template<typename V>
void release( V v ) { }
};
template<> // explicit specialization for T = std::true_type
struct Releaser<std::true_type>
{
template<typename V>
void release( V v ) { delete[] v; }
};
template <class T>
class Example
{
private:
T data;
public:
Example(): data(T()) {}
Example(T typeData): data(typeData) {}
typedef typename std::is_pointer<T>::value_type isptr_type;
~Example() {
Releaser< isptr_type >::release( data );
}
};
但是需要知道新调用的形式,所以使用删除或删除[]。
我建议你在需要Example
持有指针时T
使用std::unique_ptr
。如果T
是一个原始指针,那么它根本不拥有它,也不应该删除它。
如果需要Example
来初始化指针,请将其专用于std::unique_ptr
并在默认构造函数中调用std::make_unique
。
template<typename T>
class Example<std::unique_ptr<T>> {
Example() : data{std::make_unique<T>()} {}
/* rest of the class */
};
如果你这样做,你不应该专门化你的类,T*
做一个new
,因为你不能初始化非拥有的指针。您应该在构造函数中接收它,如果您不希望它为 null,则可以禁用原始指针的默认构造函数。
template<typename T>
class Example<T*> {
Example() = delete;
Example(T* data_) : data{data_}
/* data is not an owning pointer. No need for a destructor */
/* rest of the class */
};
如果您遵循这些规则,则内存管理应该没有问题。
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- 从类型列表中递归删除重复项会导致编译器堆空间错误 (VS2017)
- 为什么 std::make_shared 无法编译带有已删除运算符 new 的类型?
- 将类型添加到现有模板而不删除 c++17
- 删除[]具有不同类型的未定义行为?
- 创建模板类型而不新建/删除
- 从 Typedef 数据类型中删除常量
- 当类型适当的构造函数可用时,为什么一个编译器尝试使用已删除的副本构造函数
- 删除对象(具有不同类型)的引用时会发生什么情况?
- 根据模板类型有条件地删除变量
- 从浮点数中删除小数部分但保留类型的有效方法
- 从自定义数据类型向量中删除重复元素
- C++ 模板<类型名 T> 删除
- 错误:在类型 "blah blah" 的绑定引用中删除限定符以初始化"some other blah blah"
- 为什么许多标准库类型在 C++20 中删除 operator!=?
- 如何从指针类型和指针到指针类型中删除__unaligned说明符
- 为什么在某些情况下从函数返回类型中删除 cv 限定符?
- C++ - 按自定义数据类型向量的值删除元素
- c ++ 我是否需要手动删除指向另一个具体类型的 void* 指针?
- 如何删除类内类类型的类成员指针