简体   繁体   English

什么时候应该使用对象向量而不是指针向量?

[英]When should I use a vector of objects instead of a vector of pointers?

I have a collection of polymorphic objects, all derived from my Animal class: Cat, Dog, and MonkeyFish.我有一组多态对象,它们都来自我的 Animal class:Cat、Dog 和 MonkeyFish。

My usual mode of operation is to store these objects in a vector of Animal pointers, like so:我通常的操作模式是将这些对象存储在 Animal 指针向量中,如下所示:

std::vector< Animal * > my_vector; std::vector< 动物 * > my_vector;

my_vector.push_back( new Animal_Cat() );
my_vector.push_back( new Animal_Dog() );
my_vector.push_back( new Animal_MonkeyFish() );

And life is great...or is it?生活很美好……或者是吗?

I've recently been told that I should really try to avoid allocating memory in this fashion, because it makes memory management a chore.最近有人告诉我,我真的应该尽量避免以这种方式分配 memory,因为它使 memory 管理成为一件苦差事。 When I need to destroy my_vector, I have to iterate through all the elements and delete everything.当我需要销毁 my_vector 时,我必须遍历所有元素并删除所有内容。

I don't think that I can store a vector of references (I might be wrong about this), so it seems like storing a vector of Animal objects is my only alternative.我不认为我可以存储引用向量(我可能对此错了),所以似乎存储 Animal 对象的向量是我唯一的选择。

When should I choose to use a vector of pointers versus a vector of objects?我什么时候应该选择使用指针向量而不是对象向量? In general, which method is preferable?一般来说,哪种方法更可取? (I would like to reduce object copying as much as possible.) (我想尽可能减少 object 复制。)

You should use a vector of objects whenever possible;您应该尽可能使用对象向量; but in your case it isn't possible . 但在你的情况下这是不可能的

Containers of pointers let you avoid the slicing problem.指针容器可以让您避免切片问题。 But then you have to call delete on each element, like you are doing.但是你必须在每个元素上调用 delete ,就像你正在做的那样。 That's annoying but possible.这很烦人,但有可能。 Unfortunately there are cases (when an exception is thrown) where you can't be sure that delete is properly called, and you end up with a memory leak.不幸的是,在某些情况下(当抛出异常时),您无法确定正确调用了 delete,最终会导致 memory 泄漏。

The main solution is to use a smart pointer.主要的解决方案是使用智能指针。 Pre-C++11 comes with auto_ptr , but that cannot be used in a standard container . Pre-C++11 带有auto_ptr但不能在标准容器中使用 C++11 has std::unique_ptr and std::shared_ptr which are designed to be usable in containers (I prefer std::unique_ptr unless I really need reference counting). C++11 具有std::unique_ptrstd::shared_ptr ,它们被设计为可在容器中使用(我更喜欢std::unique_ptr ,除非我真的需要引用计数)。 If you can't use C++11, the best solution is Boost smart pointers .如果不能使用 C++11,最好的解决方案是Boost smart pointers

In this case, storing a vector of Animal would not work for you, as your animals have different sizes, and you wouldn't be able to store the derived objects in the spaces intended to hold the base class.在这种情况下,存储Animal的向量对您不起作用,因为您的动物具有不同的大小,并且您将无法将派生对象存储在用于保存基本 class 的空间中。 (And even if they're the same size, you won't get the intended polymorphic effect, as base class methods will be executed - the virtualness of a method doesn't come into play unless you access it through a pointer or reference.) (即使它们的大小相同,您也不会获得预期的多态效果,因为将执行基本的 class 方法 - 除非您通过指针或引用访问方法,否则方法的虚拟性不会发挥作用。 )

If you want to avoid the annoyance of managing the memory yourself, you could consider storing a smart pointer such as a shared_ptr (note that auto_ptr doesn't work with STL containers, according to Max Lybbert), or some variant thereof.如果您想避免自己管理 memory 的烦恼,您可以考虑存储一个智能指针,例如shared_ptr (请注意,根据 Max Lybbert 的说法, auto_ptr不适用于 STL 容器)或其一些变体。 That way you can still use your polymorphic class, but it's a little less work for you.这样你仍然可以使用你的多态 class,但对你来说工作量少了一点。

There's no real hard and fast rules about when to use objects and pointers, although it's worth noting that in some cases, like yours, objects just aren't going to work for you.关于何时使用对象和指针并没有真正的硬性规定,尽管值得注意的是,在某些情况下,比如你的情况,对象对你不起作用。 I tend to use objects whenever nothing precludes it though, although you do have to be concerned about expensive copy operations as you note (although sometimes they can be ameliorated by passing containers by reference).我倾向于在没有任何限制的情况下使用对象,尽管您确实必须注意昂贵的复制操作(尽管有时可以通过引用传递容器来改善它们)。

Rather than using shared_ptr with standard STL containers, take a look at the Boost Pointer Container Library .与其将 shared_ptr 与标准 STL 容器一起使用,不如查看Boost Pointer Container Library It is designed to solve exactly this problem.它旨在解决这个问题。

If you ever hear the argument but it'll be so costly to copy them structures all the time when you want to use full objects instead of pointers in a vector, then your 2 main arguments are:如果您曾经听到过这个论点,但是当您想使用完整对象而不是向量中的指针时,一直复制它们的结构会非常昂贵,那么您的两个主要 arguments 是:

  1. We don't need to worry about the lifetime issues of the pointers, which means no leaks from that particular code (unless, of course, the structures themselves have pointer data, but that's another story).我们不需要担心指针的生命周期问题,这意味着特定代码不会泄漏(当然,除非结构本身具有指针数据,但这是另一回事)。
  2. The data locality of adjacent structures in memory will boost performance in typical usage scenarios, not slow things down like pointer indirection would (relatively speaking). memory 中相邻结构的数据局部性将提高典型使用场景中的性能,而不是像指针间接(相对而言)那样减慢速度。

The added cost of copying is normally taken when adding stuff to the container, not when using the data - think a bit about it: what do you do most?复制的额外成本通常是在向容器中添加内容时产生的,而不是在使用数据时产生的——想想看:你最常做什么? add items or use them?添加项目或使用它们?

However, when adding polymorphical objects, the pointers are necessary to avoid slicing.但是,当添加多态对象时,指针对于避免切片是必要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM