何时使用向量中的对象以及何时使用指向向量中对象的指针? [关闭]

Posted

技术标签:

【中文标题】何时使用向量中的对象以及何时使用指向向量中对象的指针? [关闭]【英文标题】:When to use an object in a vector and when to use a pointer to an object in a vector? [closed] 【发布时间】:2014-09-17 08:27:52 【问题描述】:

当您实例化对象并将它们存储在向量中时。 这三者之间的优缺点是什么,应该在什么情况下使用它们?

对象:

std::vector<obj> collection;
collection.push_back(obj);

指向对象的指针:

std::vector<obj*> collection;
collection.push_back(new obj);

智能指针:

std::vector<std::unique_ptr<obj>> collection;
collection.push_back(std::unique_ptr<obj>(new obj));

【问题讨论】:

这取决于您要处理的对象的生命周期 这还取决于您的对象是否可以安全和/或有效地复制。 @MarcoA。在 RAII 和 smart Pointer 的情况下,对象的生命周期不取决于 std::vector 的生命周期吗? @worker11811 是的。在这种情况下,您几乎总是最好使用第一种方法(我当然不会有资格作为 RAII)。 简短回答 - 使用对象,除非你不能,在这种情况下使用智能指针 【参考方案1】:

如果对象类型支持复制和赋值,你应该 避开指针,并将对象放入向量中(和 其他任何地方——你可能不应该有任何指针 到这样一个对象)。

如果对象类型具有标识,并且不支持复制和 分配(或仅支持复制以实现 clone 函数),那么您需要将指针保留在 向量。是智能指针还是原始指针取决于什么 向量的用途,以及有关该向量的策略是什么 对象的生命周期是。根据我的经验,大多数时候, 矢量用于导航,在这种情况下,您应该使用 原始指针。

【讨论】:

【参考方案2】:

我个人会尽可能多地使用第一个选项,除非有令人信服的理由使用另一个(其他两个几乎相同,所以差别不大)。

主要原因是它可以生成更简洁的代码,而且几乎可以肯定它更适合 RAII (http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization),因为编译器生成的代码没有任何泄漏。这里的一些人指出性能问题是有效的,但它们比大多数人认为的要少。

所以底线(恕我直言)是:除非有令人信服的理由不这样做,否则请选择最简单和最干净的选择。除非绝对必要,否则不要在应用程序中添加不必要的复杂性。由于大多数时候甚至不需要过早的优化,我已经看到了太多的代码错误。

【讨论】:

【参考方案3】:

第一种方法是经典的方法,对象将在容器生命周期结束时销毁。它可能具有像std::sort 这样的操作的缺点,与简单的指针相比,其中涉及大量的移动(如果这在特定对象的情况下完全是个问题)。请注意,这可能是支持复制/分配的对象的首选方法。

第二种方法可能具有更高的速度(在容器中保存复制/移动性能较差的大型对象总是一个坏主意),但缺点是必须自己处理释放内存,除非您想保留容器销毁后周围的那些物体。

第三种方法在排序操作方面或多或少与第二种方法一样快,而且它具有使用智能指针的优势,可确保在容器超出范围时自动释放内存。

这真的归结为您的对象的预期生命周期范围以及您的对象可以如何有效地复制。 为您的预期测试用例做一些分析,不要先验地决定应该使用哪个(正如 James 指出的那样,这可能是过早优化的情况)。

【讨论】:

如果分析器这样说,您最终可能不得不使用指针而不是复制,但这很少见。特别是如果您使对象支持移动语义。对值对象使用指针是过早优化的经典案例。 对,我相信这个问题没有单一的答案。 我前段时间在一个项目中使用了智能指针方法,由于我们传递的对象的大小(>1GiB),它是必需的。对于其他任何事情,我倾向于第一种方法大部分时间 @Baldrickk 哇,从未使用过那么大的对象。这为“按价值传递”提供了全新的意义,更多的是“通过大象”【参考方案4】:

如果您的对象是简单数据,那么第一个选项总是最好的。新内存由vector对象在内部分配和管理,所以你不用担心。

【讨论】:

【参考方案5】:

    对象的向量。对于一般按值传递、易于复制的项目很有用。

    原始指针向量。对于更复杂的对象(您不想复制的对象),复制效率很高,但您必须在某个地方管理这些指针的生命周期。即使您在从向量中删除项目时删除,您也必须知道没有悬空的。在对象的生命周期在其他地方管理并且您知道这些指针将保持有效并且您只想将它​​们泵入向量以供某些用途的情况下,这可能是最佳方法,例如返回较大集合子集的 API 可以作为指向这些对象的指针向量来实现。

    更常见的是shared_ptr 已用于此,因为向量拥有一个副本,而提取一个以读取/使用的人将获得另一个副本,因此不会出现生命周期问题。使用 unique_ptr 它几乎是一个策略,它由向量拥有,并且 (2) 的主要原因是在从向量中删除它时不必手动删除它。向量需要包装在一个控制它的类中。多年来,当您不存储对象本身以保证生命周期的一般安全时,这里使用 shared_ptr 一直是普遍推荐的构造。

【讨论】:

以上是关于何时使用向量中的对象以及何时使用指向向量中对象的指针? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

存储在向量中的对象,它们何时被销毁?

C ++:在向量中插入啥 - 指针或引用,向量何时复制它的元素?

何时以及如何为离散卷积进行零填充?

指向向量中对象的指针有时指向向量中的不同对象

何时向托管对象添加类别以及何时使用瞬态属性?

如何从 C++ 中的“指向对象的指针”向量访问对象