我需要创建一个对象池来消除动态分配。使用std :: stack来包含已分配对象的指针是否有效?
我怀疑每次将释放的对象推回堆栈时,都会动态分配新的堆栈元素。我对吗?我应该使用std :: vector来确保没有分配新内容吗?
答案 0 :(得分:4)
堆栈是否适合您的特定目的是我不会处理的问题。现在,如果您担心分配的数量,std :: stack的默认内部容器是std :: deque<>。它不需要在每次推送中为堆栈分配新的内存(只要它有空间),并且当它分配时,它不需要将所有现有元素重新定位为std :: vector<>将。
你可以告诉堆栈使用std :: vector<>作为具有第二个模板参数的基础容器:
std::stack< int, std::vector<int> > vector_stack;
答案 1 :(得分:2)
指针的STL容器对它们指向的对象没有任何作用,这取决于你,所以你有责任不泄漏任何内存等。看看Boost Pointer Container Library或尝试存储实际的对象从长远来看,你会省去自己的麻烦。
如果您希望减少容器所做的动态分配量,并且您大致知道需要存储多少个对象,则可以使用vector的'reserve()'方法,该方法将预先分配你一次要求的记忆。
您还可以在构造函数中指定所需的记录数,但这种方式将为您创建x对象,然后存储它们,这可能不是您想要的。
如果由于某些技术原因动态分配完全失败,您可能想尝试使用boost::pool作为分配器,(如您所知,如果您不想要,可以指定不同的std库内存分配器)使用默认值)。
那就是说,当我测试它时,默认的总是更快,至少用g ++,所以它可能不值得努力。确保您对其进行分析,而不是假设您可以对标准委员会进行编码!
答案 2 :(得分:0)
由于nothrow-guarantee,在免费期间执行 ANY 分配错误。如果你必须做一个免费的alloc,并且alloc抛出你把指针放在哪里?您可以安静地捕获异常并泄漏或传播异常。传播异常意味着将使用YourObject
的对象放入STL容器中。泄漏就是泄漏。在任何一种情况下,你都违反了规则。
但是使用什么数据结构取决于你的对象生命周期控制习惯。
成语是一个与工厂方法和freeInstance一起使用的对象池
YourObject* pO = YourObject::getInstance(... reinitialize parameters ...);
......object public lifetime....
pO->freeInstance();
或与特定于类的运算符new / operator delete(或分配器)一起使用的内存池?
YourObject::operator new(size_t);
......object public lifetime....
delete pO;
如果它是一个对象池,你知道在发布的代码和deque中最好使用YourObject *的使用向量的数量,或者最好是一个循环缓冲区(因为deque没有保留,所以你必须在动态添加它自定义循环缓冲区正是您想要的调试代码并保留近似数字。在发布中分配LIFO,在调试中分配FIFO,这样您就可以在调试中获得历史记录。
在没有免费对象的路径中,请记住在动态创建对象之前在reserve(nMade+1)
集合之前执行YourObject*
。
(这个保留的原因有两个。首先,它必须在createInstance
时间完成。第二,它简化了代码。否则你有可能在{{1}中抛出一个std :: badalloc这可能使析构函数保证难以保证。 OUCH !例如 - Y类中有一个freeInstance
,并且其中YourObject*
为freeInstance
析构函数 - 如果你没有为YourObject*
*保留空间,那么在YourObject
时将指针存储在哪里?如果你之后在freeInstance
中保留了空格那么你必须捕获保留的std :: badalloc,释放刚制作的getInstance
和YourObject
。)
如果是内存池,那么在内存块中使用发布中的侵入式单链表和调试中的双链表(我假设rethrow
)BTW那里有很多MemoryPool实现。再次在发布中分配LIFO,在调试中分配FIFO,这样您就可以在调试中获得历史记录。
BTW如果你使用工厂习惯用法,请不要跳过重载的getIntances()并添加reinit方法。这只是开启了重新启动电话的可能性。 getInstance方法是你的“构造函数”,因为它们将对象转换为你想要的状态。请注意,在对象池的情况下,您需要一个freeInstance,它可能需要对对象执行“类似析构函数”的操作。
在这种情况下,谈论“公共类不变量”和“私有类不变量”是有道理的 - 对象处于一种不稳定的状态,公共类不变量可以在不时满足免费游泳池。它与sizeof(YourObject)>=2*sizeof(void*)
一样关注YourObject
但是所有的公共类不变量都可能不满足。获取实例并确保满足其公共不变量是YourObject :: getInstance的工作。以互补的方式,freeInstance释放可能由getInstance获取的资源,以确保满足“公共类不变量”,可以在空闲列表中的“空闲时间”对象期间释放。
发布中的LIFO还具有 SIGNIFICANT 缓存最后使用的对象/块的好处,因为如果有足够多的对象/块,甚至页面如果数字更大!但是你可能已经意识到这一点,因为你决定使用堆栈。
强文