检查和删除无法按预期工作

时间:2017-02-25 04:50:01

标签: c++ c++11

我有一个模板类

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的内部,我之所以离开,因为它不是完全有必要帮助回答这个问题。我不确定为什么出现这个错误,因为我在检查数据之前确保数据是一个指针,然后再尝试删除它。

有人可以进一步了解为什么这不起作用/替代方法? (注意:不能使用智能指针进行此分配)

2 个答案:

答案 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);
}