这是我的方案(为简洁起见,我已经取出了权限和实例变量,只有相关的方法):
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&lt;&gt; :: Item不应释放实际对象的事实。这更像是一个理解模板的问题。我需要为Item析构函数指定一个显式模板,以便在ItemType为指针时以及何时不指示它。
这可能吗?什么是潜在的设计/泄漏坑?感谢。
答案 0 :(得分:0)
你可能正在寻找partial template specialization。您可以做的是ItemType *
的特殊情况,并让您的内部Item
的析构函数不执行删除。有点像:
// 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) {}
};
答案 1 :(得分:0)
答案是:不。当我有一个指针容器时,我不希望容器拥有 pointees 。事实上,没有人希望这样,标准库容器不会这样工作。
如果不出意外,你会通过对每个元素的指针如何分配以及谁拥有它们做出不合逻辑的假设来制造大量的内存管理。
该列表没有new
这些人,所以它不会delete
他们。简单!