我写了一个类来包含我的对象。 代码是:
class objectPool
{
private:
struct itemType_{uint count; void* object;};
std::multimap< std::string, itemType_ > pool_;
public:
template<class T>
bool addItem(std::string key, T*& object)
{
std::multimap< std::string, itemType_ >::iterator
i = pool_.find(key);
if(i != pool_.end())
{
object = (T*)(*i).second.object;
(*i).second.count++;
return true;
}
i = pool_.insert(std::pair<std::string,itemType_>(key, (itemType_){1, NULL}));
object = (T*)(*i).second.object;
return false;
}
template<class T>
bool removeItem(std::string key)
{
std::multimap< std::string, itemType_ >::iterator
i = pool_.find(key);
if(i != pool_.end())
{
if((*i).second.count == 1)
{
//important to call the appropriate destructor
delete ((T*)(*i).second.object);
pool_.erase(i);
}
else
(*i).second.count--;
return true;
}
return false;
}
};
测试代码:
#include "objectPool.h"
class testClass
{
public:
~testClass()
{
// I should get here at least once
std::cout << "I am deleted teehee";
}
};
testClass* test;
objectPool myPool;
int main () {
if(!myPool.addItem<testClass>("baba", test))
{
test = new testClass;
}
myPool.removeItem<testClass>("baba");
}
由于某种原因,我的测试对象的析构函数不希望被调用。 第一个问题:为什么?哪里错了?
秒:我应该使用auto_ptr吗? (虽然我想避免使用模板......)
第三个:有更好的( - 看)解决方案吗? (使用或不使用模板)
第四种:有没有办法通过没有模板的void指针调用构造函数(或者不知道原始类型)?
非常感谢! :d 对不起我非常好的英语(不是我的母语,虽然......)
答案 0 :(得分:5)
您正确地将NULL存储到T *引用中,但这是对局部变量的引用。当您稍后通过调用new更新该本地时,这对存储在池中的项目没有影响。
解决此问题的更简单方法是使用new T
在addItem函数内创建对象。
至于你的另一个问题,一种在不知道原始类型的情况下调用析构函数的方法,就没有办法做到这一点。但是有一个技巧可以用于模板。您可以创建一个类似下面的模板函数,然后传递一个函数指针。
template<typename T>
void deleter(void *ptr)
{
delete static_cast<T*>(ptr);
}
删除作为一种简单类型,你可以输入dede并传递指针:
typedef void (*deleter_func)(void *);
要获取指向它的指针,只需在addItem函数中执行以下操作:
deleter_func myDeleter = &deleter<T>;
然后:
myDeleter(somePtr);
删除时不需要知道somePtr的类型,只需要保留指向删除器的指针即可。您也可以将此方法用于shared_ptr,它可以使用删除器参数。
答案 1 :(得分:0)
我猜是因为你将{1, NULL}
插入地图会出错。更改主函数中test
的值不会影响地图的内容。
答案 2 :(得分:0)
由于某种原因,我的测试对象的析构函数不希望被调用。第一个问题:为什么?哪里错了?
您的测试代码错误。您将一些未初始化的指针添加到结构中。试试这个:
int main () {
test = new testClass();
if(!myPool.addItem<testClass>("baba", test))
{
// Duplicate, I presume...
}
myPool.removeItem<testClass>("baba");
}
秒:我应该使用auto_ptr吗?
std::auto_ptr
是为动态分配的本地变量而设计的,它不是为容器实现而设计的。无论如何,您当前的设计限制了这一点。但是,我会将测试代码编写为
int main () {
std::auto_ptr<testClass> test(new testClass());
if(myPool.addItem<testClass>("baba", test.get()))
{
test.release();
}
myPool.removeItem<testClass>("baba");
}
第三种:有更好的( - 看)解决方案吗?
是的,提升中有一些type-safe heterogenous container。我会看那个。
第四种:有没有办法通过没有模板的void指针调用构造函数(或者不知道原始类型)?
如果要在预分配的内存中构造对象,可以使用placement new运算符。 std::vector
做了很多。但是,如果不知道类型,就无法构造对象。你如何指定要调用的类型的构造函数?如果您需要,可能需要查看factory method pattern。