我通常避免使用std :: list,但是在我存储指针的情况下,使用std :: list会更有利,因为我可以随机插入指针而不必移动所有其他指针吗?在[{1}}
上存在哪些优点和缺点由于
答案 0 :(得分:9)
由于指针的复制构造很简单,因此这里的决定不是关于一个或另一个是否更适合存储指针,而是更好地满足您的需求。
如果你真的需要做很多随机插入(和删除?),那么list
可以更好地工作,虽然这不是一个简单的决定 - 也许带有保留空间的vector
会更好,即使这样。您是否希望list
的每节点开销只是存储指针?在32位Windows上,list
中每个条目的12个字节加上堆管理开销,每个条目总共20多个字节。这也无助于数据本地化随着时间的推移。同时,vector
每个条目使用四个字节(再次使用32位)并保证将其元素存储在一个连续的块中。
除非将指针元素包装为某种类型的智能指针,否则必须以erase
/ clear
/破坏容器的方式处理内存清理。另一种简化Some*
内存管理的方法是Boost pointer containers。
有关list
,vector
和deque
的分析,另请参阅here。就个人而言,我越来越认为list
在主流中没有用处。
答案 1 :(得分:3)
我认为它是 特别是指针 ,即使在随机位置有许多插入/删除,也应该考虑使用std::vector
代替std::list
。指针复制非常便宜(事实上,我希望我的标准库实现 使用CPU内在函数 来执行此操作),以便{{1}的更高位置对于随机插入/删除,数据可能远远超过std::vector
在理论上更好的适应度。
无论如何,您必须测量您的应用程序(以及不人工测试用例)才能确定。
答案 2 :(得分:1)
一般来说,您的首选应该是vector
- 当您存储指针时也是如此。
将决定与C中的这个问题进行比较(-ish):我什么时候选择
struct linked_items { element *item; linked_items *next; };
在
element* items[]; /* array of pointers to items */
有些情况,但首先检查您是否可以应用“更简单”的数据结构,即vector
。
答案 3 :(得分:0)
通常,当您需要一个存储某个东西的容器然后随机删除它时,最好的是set
。要删除某些内容,您需要先找到它,对于向量和列表,O(n)
和对于集合O(log(n))
。如果找到则删除它是即时列表,但O(n)
表示向量,而O(log(n))表示集合。
所以:
vector
从中搜索或删除
容器; list
; set
。 vector
是最有效的内存和缓存。如果您知道元素的数量,那么使用reserve()
可以使其100%的内存效率。
答案 4 :(得分:0)
基于基准测试研究,我更喜欢使用向量,除非有其他强大的用例来支持链表(带有一些开销信息)。但是以更好的方式处理插入和移除效率低下(平均而言)。
vector<SomeObject*> vecSomeObjectPointers;
vector<size_t> vecInvalidPointerIndices;// could be zero size, if no objects are removed
void AddNewObject()
{
SomeObject* ptrSomeObject = new SomeObject;
ptrSomeObject->PopulateSomeObject(); // add any extra memory if needed by SomeObject members
ptrSomeObject->DoAnyOtherWorkOnSomeObjectBeforeStoring();
size_t TotalInValidIndices = vecInvalidPointerIndices.size();
if(TotalInValidIndices > 0)
{
//re-use the invalid location/index of vector to hold new object
vecSomeObjectPointers[vecInvalidPointerIndices[TotalInValidIndices-1]] = ptrSomeObject;
vecInvalidPointerIndices.pop_back();
}
else vecSomeObjectPointers.push_back(ptrSomeObject); // new Object pointer at the end
}
void DeleteAnExistingObject()
{
//Find the index of the object to be deleted based on certain input criteria. Ex: value stored etc..
SomeObject* ptrSomeObject;
for(auto& itr=vecSomeObjectPointers.begin(); itr != vecSomeObjectPointers.end(); ++itr)
{
ptrSomeObject = itr;
if(ptrSomeObject->SomeObjectDeletionCriteriaSatisfied())
{
// make sure to delete any extra memory allocated to SomeObject members
delete ptrSomeObject; // re-claim allocated memory
// just invalidate the pointer info rather deleting it from vector to save re-shuffling time
itr = NULL;
//Store the corresponding index to be used for holding a new object to be inserted next time
vecInvalidPointerIndices.push_back(itr - vecSomeObjectPointers.begin());
}
}
}
void DoSomeWorkOnAnExistingObject()
{
SomeObject* ptrSomeObject;
for(auto& itr=vecSomeObjectPointers.begin(); itr != vecSomeObjectPointers.end(); ++itr)
{
if(itr == NULL) continue;
//Do some work on object data to maintain it
ptrSomeObject = itr;
}
}
欢迎任何其他想法......
答案 5 :(得分:0)
我假设你问[std::list<Foo*>
由于许多间接而导致真的很慢]
std::vector<Foo*> objects
Vs的
std::list<Foo> objects
std::vector
:
Foo
个对象Foo
可以是抽象的delete
您的对象 std::list
:
delete
个对象Foo
个对象Foo
不能是抽象的编辑:
我意识到有一种情况是std :: vector不起作用,除非你的对象归其他人所有。考虑这个递归的事情
class Foo
{
public:
~Foo(); /**<Now this must be recursive, otherwise it would need std::stack, which results in potential exception from dtor!*/
private:
std::vector<Foo*> m_children;
};