我遇到以下问题。考虑这个(非常简化的)示例。我正在使用我们现有的一个模板类,我可以添加(最多一点)一些通用功能:
template<typename T> class myClass
{
public:
typedef T element_type;
explicit myClass(T* p = 0) : ptr(p) {}
~myClass() { delete ptr; };
......
private:
T* ptr;
};
我也在使用外部库(我显然无法调整),其中包括(假设)struct notMine
。由于这是一个C风格的库,我会做一些notMine* nmPtr = createNotMine();
调用,当我完成时我需要记住freeNotMine(nmPtr);
。
现在我想使用myClass
指向notMine
结构的指针,但问题是当myClass
超出范围时,我'忘记'释放{{1}结构,它改为调用'删除'。
解决这个问题的好方法是什么?
答案 0 :(得分:4)
立即实施
鉴于可以修改类(保持向后兼容性),您可以扩展类以包括自定义删除器来管理资源(具有合适的默认值)。然后可以为类需要维护的每种类型实现自定义删除。
template <typename T>
struct DefaultDeleter {
void operator()(T* ptr) const {
delete ptr;
}
}
struct NotMineDeleter { // or a specialisation of DefaultDeleter
void operator()(notMine* nmPtr) const {
if (nmPtr)
freeNotMine(nmPtr);
}
}
template<typename T, typename Deleter = DefaultDeleter<T> >
class myClass
{
public:
typedef T element_type;
explicit myClass(T* p = 0) : ptr(p) {}
~myClass() { deleter_(ptr); };
......
private:
Deleter deleter_;
T* ptr;
};
myClass
现在可以按如下方式用于外部库;
myClass<notMine, NotMineDeleter> obj(createNotMine());
您还需要通过制作myClass
(C ++ 03),删除它们private:
来处理您的班级=delete;
的副本和作业(C ++ 11)或者适当地实现,即实现完整的拷贝和赋值语义。
您已批评副本和分配已正确实施(这也需要notMine*
指针的情况)。如果情况并非如此,那么您可能会遇到更多问题。
C ++ 11还带来了移动语义,可以实现将所有权从myClass
的一个实例转移到另一个实例。
更好
将std::unique_ptr
或std::share_ptr
与调用freeNotMine(nmPtr)
的自定义删除工具一起使用。
替代上面的双删除
使用模板专业化,可以简化实现(但基本上仍然维护每种类型的删除器),如下所示;
template <typename T>
struct Deleter {
void operator()(T* ptr) const {
delete ptr;
}
}
template <>
struct Deleter<notMine> {
void operator()(notMine* nmPtr) const {
if (nmPtr)
freeNotMine(nmPtr);
}
}
template<typename T>
class myClass
{
public:
typedef T element_type;
explicit myClass(T* p = 0) : ptr(p) {}
~myClass() { deleter_(ptr); };
......
private:
Deleter<T> deleter_;
T* ptr;
};
myClass
现在可以按如下方式用于外部库;
myClass<notMine> obj(createNotMine());