1

这是我的场景(为简洁起见,我取出了权限和实例变量,只取出了相关方法):

template <typename ItemType>
class LinkedList
{
    class Item
    {
        Item(ItemType theObj, bool freeObj);
        ~Item();
    };

    void add(LinkedList<ItemType>::Item item);
};

template <typename ItemType>
LinkedList<ItemType>::Item::~Item()
{
    if(freeObj) {
        delete obj;
    }
}

在我的代码中,我这样使用它:

// works great
LinkedList<MyObject*> mylist;
mylist.add(LinkedList<MyObject*>::Item(new MyObject(), false));

// won't compile because you cannot use delete operator on a non-pointer
LinkedList<MyObject> mylist;
mylist.add(LinkedList<MyObject>::Item(MyObject(), false));

让我们抛开 LinkedList<>::Item 不应该释放实际对象的事实。这更像是一个理解模板的问题。我需要为 Item 析构函数指定一个显式模板,以便在 ItemType 是指针和不是指针时进行处理。

这可能吗?有哪些潜在的设计/漏坑坠落?谢谢。

4

2 回答 2

0

答案是:不要。当我有一个指针容器时,我不希望容器拥有指针。事实上,没有人预料到这一点,标准库容器也不是这样工作的。

如果不出意外,您会通过对每个元素的指针是如何分配以及谁拥有它们做出不合逻辑的假设,从而使内存管理变得一团糟。

该列表没有new这些指针,所以它不应该是delete它们。简单!

于 2013-11-06T03:20:37.320 回答
0

您可能正在寻找部分模板专业化。您可以做的是 a 的特殊情况,ItemType *并让您的 internalItem的析构函数不执行删除。类似于以下内容:

// General form
template <typename ItemType>
class LinkedList
{
public:
    class Item
    {
        Item(ItemType theObj, bool);
        ~Item() {}
    };

    void add(Item item);
};

// specialize for when ItemType is a pointer
template <typename ItemType>
class LinkedList <ItemType *>
{
public:
    class Item
    {
        Item(ItemType *theObj, bool freeObj);
        ~Item() 
        {
          if(freeObj) delete obj;
        }
    };

    void add(Item item);
};

编辑:回复您的第一条评论。我认为即使不依赖 SFINAE,您也可以在没有太多代码重复的情况下完成此操作。我要做的是freeObj作为非类型参数移动LinkedList并保持class Item私有。包装器只是一个实现细节,客户端代码对此一无所知。建议的替代方案如下所示:

template <typename ItemType, bool freeObj = false>
class LinkedList
{
    template <typename T> 
    class Item
    {
        T obj;
    public:
        Item(T theObj);
        ~Item();
    };
    template <typename T>
    class Item <T *>
    {
        T *obj;
    public:
        Item(T *theObj);
        ~Item() { if(freeObj) delete obj; }
    };

public:
    void add(ItemType) {}
};

这是一个简单的演示示例

于 2013-11-06T02:13:27.170 回答