C++ 我应该存储整个对象,还是在容器中存储指向对象的指针?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/141337/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Should I store entire objects, or pointers to objects in containers?
提问by Stéphane
Designing a new system from scratch. I'll be using the STL to store lists and maps of certain long-live objects.
从头开始设计一个新系统。我将使用 STL 来存储某些长期存在的对象的列表和映射。
Question: Should I ensure my objects have copy constructors and store copies of objects within my STL containers, or is it generally better to manage the life & scope myself and just store the pointers to those objects in my STL containers?
问题:我应该确保我的对象具有复制构造函数并将对象的副本存储在我的 STL 容器中,还是自己管理生命周期和范围并将指向这些对象的指针存储在我的 STL 容器中通常更好?
I realize this is somewhat short on details, but I'm looking for the "theoretical" better answer if it exists, since I know both of these solutions are possible.
我意识到这在细节上有些不足,但我正在寻找“理论上”更好的答案(如果存在),因为我知道这两种解决方案都是可能的。
Two very obvious disadvantage to playing with pointers: 1) I must manage allocation/deallocation of these objects myself in a scope beyond the STL. 2) I cannot create a temp object on the stack and add it to my containers.
使用指针有两个非常明显的缺点:1) 我必须自己在 STL 之外的范围内管理这些对象的分配/解除分配。2) 我无法在堆栈上创建临时对象并将其添加到我的容器中。
Is there anything else I'm missing?
还有什么我想念的吗?
采纳答案by Torbj?rn Gyllebring
Since people are chiming in on the efficency of using pointers.
由于人们对使用指针的效率感到满意。
If you're considering using a std::vector and if updates are few and you often iterate over your collection and it's a non polymorphic type storing object "copies" will be more efficent since you'll get better locality of reference.
如果您正在考虑使用 std::vector 并且如果更新很少并且您经常迭代您的集合并且它是一种非多态类型存储对象“副本”将更有效,因为您将获得更好的引用位置。
Otoh, if updates are common storing pointers will save the copy/relocation costs.
Otoh,如果更新是常见的存储指针将节省复制/重定位成本。
回答by Nick Haddad
This really depends upon your situation.
这真的取决于你的情况。
If your objects are small, and doing a copy of the object is lightweight, then storing the data inside an stl container is straightforward and easier to manage in my opinion because you don't have to worry about lifetime management.
如果您的对象很小,并且对象的副本是轻量级的,那么在我看来,将数据存储在 stl 容器中是直接且易于管理的,因为您不必担心生命周期管理。
If you objects are large, and having a default constructor doesn't make sense, or copies of objects are expensive, then storing with pointers is probably the way to go.
如果您的对象很大,并且使用默认构造函数没有意义,或者对象的副本很昂贵,那么使用指针存储可能是要走的路。
If you decide to use pointers to objects, take a look at the Boost Pointer Container Library. This boost library wraps all the STL containers for use with dynamically allocated objects.
如果您决定使用指向对象的指针,请查看Boost Pointer Container Library。这个 boost 库包装了所有 STL 容器,以便与动态分配的对象一起使用。
Each pointer container (for example ptr_vector) takes ownership of an object when it is added to the container, and manages the lifetime of those objects for you. You also access all the elements in a ptr_ container by reference. This lets you do things like
每个指针容器(例如 ptr_vector)在将对象添加到容器时都会获得对象的所有权,并为您管理这些对象的生命周期。您还可以通过引用访问 ptr_ 容器中的所有元素。这可以让你做这样的事情
class BigExpensive { ... }
// create a pointer vector
ptr_vector<BigExpensive> bigVector;
bigVector.push_back( new BigExpensive( "Lexus", 57700 ) );
bigVector.push_back( new BigExpensive( "House", 15000000 );
// get a reference to the first element
MyClass& expensiveItem = bigList[0];
expensiveItem.sell();
These classes wrap the STL containers and work with all of the STL algorithms, which is really handy.
这些类包装了 STL 容器并与所有 STL 算法一起工作,这真的很方便。
There are also facilities for transferring ownership of a pointer in the container to the caller (via the release function in most of the containers).
还有一些工具可以将容器中指针的所有权转移给调用者(通过大多数容器中的 release 函数)。
回答by Torbj?rn Gyllebring
If you're storing polymporhic objects you always need to use a collection of base class pointers.
如果要存储多态对象,则始终需要使用一组基类指针。
That is if you plan on storing different derived types in your collection you must store pointers or get eaten by the slicing deamon.
也就是说,如果您计划在集合中存储不同的派生类型,则必须存储指针或被切片守护进程吃掉。
回答by EML
Sorry to jump in 3 years after the event, but a cautionary note here...
很抱歉在事件发生 3 年后跳入,但这里有一个警告...
On my last big project, my central data structure was a set of fairly straightforward objects. About a year into the project, as the requirements evolved, I realised that the object actually needed to be polymorphic. It took a few weeks of difficult and nasty brain surgery to fix the data structure to be a set of base class pointers, and to handle all the collateral damage in object storage, casting, and so on. It took me a couple of months to convince myself that the new code was working. Incidentally, this made me think hard about how well-designed C++'s object model is.
在我的上一个大项目中,我的中心数据结构是一组相当简单的对象。项目开始大约一年后,随着需求的发展,我意识到对象实际上需要是多态的。花了几个星期的困难和讨厌的脑部手术将数据结构修复为一组基类指针,并处理对象存储、转换等中的所有附带损害。我花了几个月的时间让自己相信新代码是有效的。顺便说一句,这让我认真思考 C++ 的对象模型设计得有多好。
On my current big project, my central data structure is a set of fairly straightforward objects. About a year into the project (which happens to be today), I realised that the object actually needs to be polymorphic. Back to the net, found this thread, and found Nick's link to the the Boost pointer container library. This is exactly what I had to write last time to fix everything, so I'll give it a go this time around.
在我当前的大项目中,我的中心数据结构是一组相当简单的对象。项目开始大约一年(恰好是今天),我意识到对象实际上需要是多态的。回到网上,找到了这个线程,找到了Nick的Boost指针容器库的链接。这正是我上次为了解决所有问题而必须写的内容,所以这次我会试一试。
The moral, for me, anyway: if your spec isn't 100% cast in stone, go for pointers, and you may potentially save yourself a lot of work later.
无论如何,对我来说,道德是:如果您的规范不是 100% 一成不变,请寻求指导,您可能会在以后为自己节省很多工作。
回答by Branan
Why not get the best of both worlds: do a container of smart pointers (such as boost::shared_ptr
or std::shared_ptr
). You don't have to manage the memory, and you don't have to deal with large copy operations.
为什么不两全其美:做一个智能指针的容器(例如boost::shared_ptr
或std::shared_ptr
)。您不必管理内存,也不必处理大型复制操作。
回答by Greg Rogers
Generally storing the objects directly in the STL container is best as it is simplest, most efficient, and is easiest for using the object.
通常将对象直接存储在 STL 容器中是最好的,因为它最简单、最高效,并且最容易使用对象。
If your object itself has non-copyable syntax or is an abstract base type you will need to store pointers (easiest is to use shared_ptr)
如果您的对象本身具有不可复制的语法或者是抽象基类型,您将需要存储指针(最简单的是使用 shared_ptr)
回答by Lou Franco
You seem to have a good grasp of the difference. If the objects are small and easy to copy, then by all means store them.
你似乎很清楚其中的区别。如果对象很小且易于复制,那么一定要存储它们。
If not, I would think about storing smart pointers (not auto_ptr, a ref counting smart pointer) to ones you allocate on the heap. Obviously, if you opt for smart pointers, then you can't store temp stack allocated objects (as you have said).
如果没有,我会考虑将智能指针(不是 auto_ptr,一个 ref 计数智能指针)存储到您在堆上分配的指针。显然,如果您选择智能指针,则无法存储临时堆栈分配的对象(如您所说)。
@Torbj?rnmakes a good point about slicing.
@ Torbj?rn对切片提出了一个很好的观点。
回答by 17 of 26
Using pointers will be more efficient since the containers will be only copying pointers around instead of full objects.
使用指针会更有效,因为容器只会复制指针而不是完整的对象。
There's some useful information here about STL containers and smart pointers:
这里有一些关于 STL 容器和智能指针的有用信息:
Why is it wrong to use std::auto_ptr<> with standard containers?
回答by 17 of 26
If the objects are to be referred to elsewhere in the code, store in a vector of boost::shared_ptr. This ensures that pointers to the object will remain valid if you resize the vector.
如果对象要在代码中的其他地方引用,则存储在 boost::shared_ptr 向量中。这可确保在调整矢量大小时指向对象的指针将保持有效。
Ie:
IE:
std::vector<boost::shared_ptr<protocol> > protocols;
...
connection c(protocols[0].get()); // pointer to protocol stays valid even if resized
If noone else stores pointers to the objects, or the list doesn't grow and shrink, just store as plain-old objects:
如果没有其他人存储指向对象的指针,或者列表没有增长和缩小,只需存储为普通对象:
std::vector<protocol> protocols;
connection c(protocols[0]); // value-semantics, takes a copy of the protocol
回答by Meleneth
This question has been bugging me for a while.
这个问题困扰了我一段时间。
I lean to storing pointers, but I have some additional requirements (SWIG lua wrappers) that might not apply to you.
我倾向于存储指针,但我有一些可能不适用于您的额外要求(SWIG lua 包装器)。
The most important point in this post is to test it yourself, using your objects
这篇文章中最重要的一点是自己测试它,使用你的对象
I did this today to test the speed of calling a member function on a collection of 10 million objects, 500 times.
我今天这样做是为了测试在 1000 万个对象的集合上调用成员函数 500 次的速度。
The function updates x and y based on xdir and ydir (all float member variables).
该函数根据 xdir 和 ydir(所有浮点成员变量)更新 x 和 y。
I used a std::list to hold both types of objects, and I found that storing the object in the list is slightly faster than using a pointer. On the other hand, the performance was very close, so it comes down to how they will be used in your application.
我使用 std::list 来保存这两种类型的对象,我发现将对象存储在列表中比使用指针稍快。另一方面,性能非常接近,因此归结为它们将如何在您的应用程序中使用。
For reference, with -O3 on my hardware the pointers took 41 seconds to complete and the raw objects took 30 seconds to complete.
作为参考,在我的硬件上使用 -O3 指针需要 41 秒才能完成,原始对象需要 30 秒才能完成。