我有一组多态对象,都来自我的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对象的向量是我唯一的选择。
我应该何时选择使用指针向量与对象向量?一般来说,哪种方法更可取? (我想尽可能减少对象复制。)
答案 0 :(得分:17)
您应该尽可能使用对象矢量; but in your case it isn't possible
指针容器可以避免切片问题。但是你必须在每个元素上调用delete,就像你正在做的那样。这很烦人但可能。不幸的是,有些情况(当抛出异常时)你无法确定是否正确调用了删除,并最终导致内存泄漏。
主要解决方案是使用智能指针。 Pre-C ++ 11附带auto_ptr
,but that cannot be used in a standard container。 C ++ 11有std::unique_ptr
和std::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)
如果您曾经听过这个论点,但是当您想要使用完整对象而不是向量中的指针时,复制它们的结构会非常昂贵,那么您的两个主要参数是:
复制的成本通常是在向容器中添加内容时使用,而不是在使用数据时 - 请考虑一下:您最常做什么?添加项目还是使用它们?
但是,在添加多态对象时,必须使用指针来避免切片。