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

时间:2009-02-24 00:49:43

标签: c++

我有一组多态对象,都来自我的Animal类:Cat,Dog和MonkeyFish。

我通常的操作模式是将这些对象存储在Animal指针的向量中,如下所示:

的std ::矢量<动物*> my_vector;

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

生活很美好......或者是它?

我最近被告知我应该尽量避免以这种方式分配内存,因为它使内存管理成为一件苦差事。当我需要销毁my_vector时,我必须遍历所有元素并删除所有内容。

我认为我不能存储引用的向量(我可能错了),所以看起来存储Animal对象的向量是我唯一的选择。

我应该何时选择使用指针向量与对象向量?一般来说,哪种方法更可取? (我想尽可能减少对象复制。)

4 个答案:

答案 0 :(得分:17)

您应该尽可能使用对象矢量; but in your case it isn't possible

指针容器可以避免切片问题。但是你必须在每个元素上调用delete,就像你正在做的那样。这很烦人但可能。不幸的是,有些情况(当抛出异常时)你无法确定是否正确调用了删除,并最终导致内存泄漏。

主要解决方案是使用智能指针。 Pre-C ++ 11附带auto_ptrbut that cannot be used in a standard container。 C ++ 11有std::unique_ptrstd::shared_ptr,它们可以在容器中使用(我更喜欢std::unique_ptr,除非我真的需要引用计数)。如果您不能使用C ++ 11,最佳解决方案是Boost smart pointers

答案 1 :(得分:8)

在这种情况下,存储Animal的向量对您不起作用,因为您的动物具有不同的大小,并且您将无法将派生对象存储在用于保存基类的空间中。 (即使它们的大小相同,也不会获得预期的多态效果,因为基类方法将被执行 - 除非您通过指针或引用访问它,否则方法的虚拟性不起作用。 )

如果你想避免自己管理内存的麻烦,你可以考虑存储一个智能指针,如shared_ptr(注意auto_ptr不适用于STL容器,根据Max Lybbert),或其某些变体。这样你仍然可以使用你的多态类,但对你来说它的工作量会少一些。

关于何时使用对象和指针,没有真正严格的规则,尽管值得注意的是,在某些情况下,像你的一样,对象根本不适合你。我倾向于在没有任何事情排除它的情况下使用对象,尽管你必须关注昂贵的复制操作(尽管有时它们可​​以通过引用传递容器来改善)。

答案 2 :(得分:8)

不要将shared_ptr与标准STL容器一起使用,而是查看Boost Pointer Container Library。它旨在解决这个问题。

答案 3 :(得分:1)

如果您曾经听过这个论点,但是当您想要使用完整对象而不是向量中的指针时,复制它们的结构会非常昂贵,那么您的两个主要参数是:

  1. 我们不需要担心指针的生命周期问题,这意味着 特定代码没有泄漏(当然,除非结构本身有指针数据,但这是另一个故事)。
  2. 内存中相邻结构的数据位置将提升典型使用场景中的性能,而不是像指针间接一样缓慢(相对而言)。
  3. 复制的成本通常是在向容器中添加内容时使用,而不是在使用数据时 - 请考虑一下:您最常做什么?添加项目还是使用它们?

    但是,在添加多态对象时,必须使用指针来避免切片。