我有一个模板类
template <class T>
class Node
{
private:
T data;
public:
Node<T> *next;
Node(T initial);
~Node();
};
和析构函数如下:
template <class T>
Node<T>::~Node()
{
if (std::is_pointer<T>::value)
{
delete this->data;
}
}
template <class T>
LinkedList<T>::~LinkedList() {
Node<T> *this_nodes = this->head;
Node<T> *next = NULL;
while (this_nodes)
{
next = this_nodes->next;
delete this_nodes;
this_nodes = next;
}
}
但是,当我尝试使用带有C ++ 11的g ++进行编译时,使用以下驱动程序代码
LinkedList<int> list;
list.insert(5);
assert(list.read() == 5);
我收到以下错误:
error: type ‘int’ argument given to ‘delete’, expected pointer
节点是LinkedList的内部,我之所以离开,因为它不是完全有必要帮助回答这个问题。我不确定为什么出现这个错误,因为我在检查数据之前确保数据是一个指针,然后再尝试删除它。
有人可以进一步了解为什么这不起作用/替代方法? (注意:不能使用智能指针进行此分配)
答案 0 :(得分:1)
if
语句是在代码中创建运行时分支的工具。不是条件编译。展开模板代码时,它看起来与此类似:
Node<int>::~Node()
{
if (false)
{
delete this->data;
}
}
您仍在删除int,即使它在死分支内,代码仍然有效。
解决方案应该真的不要触摸指针。您希望此代码输出什么?
struct A { ~A() { std::cout << "~A()" << std::endl; } };
auto a = new A;
std::vector<A*> vec;
vec.emplace_back(a);
vec.clear();
答案是什么。该向量将删除其缓冲区,但不会删除您的数据。如果您希望这样,请使用std::unique_ptr
:
struct A { ~A() { std::cout << "~A()" << std::endl; } };
auto a = new A;
std::vector<std::unique_ptr<A>> vec;
vec.emplace_back(a);
vec.clear();
现在任何人都希望此代码输出~A()
。您的代码也是如此。通常,您希望类型管理自己并释放任何获得的资源。因此,代码中的更改只是删除删除并假定要管理自己的类型。
如果你真的想要这样做, ,我真的不推荐 ,你可以这样做:
template<typename T>
void deleteIfPtr(T* ptr) { delete ptr; }
template<typename T>
void deleteIfPtr(const T&) { /* else, do nothing */ }
template <class T>
Node<T>::~Node()
{
deleteIfPtr(this->data);
}
答案 1 :(得分:0)
您无法使用逻辑
if (std::is_pointer<T>::value)
{
delete this->data;
}
编译器将编译行
delete this->data;
无论用于实例化Node
的类型如何。
你必须使用不同的东西。例如:
template <typename T> struct Deleter
{
static void deleteObject(T) { /* Do nothing */ }
};
template <typename T> struct Deleter<T*>
{
static void deleteObject(T* obj) { delete obj; }
};
template <class T>
Node<T>::~Node()
{
Deleter<T>::deleteObject(data);
}