何时使用向量中的对象以及何时使用指向向量中对象的指针?

时间:2014-09-17 08:27:52

标签: c++ pointers vector raii

实例化对象并将其存储在向量中时。 这三者之间的利弊是什么?在哪种情况下应该使用它们?

对象:

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{}));

5 个答案:

答案 0 :(得分:3)

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

如果对象类型具有标识,并且不支持复制和 赋值(或仅支持拷贝才能实现 一个clone函数),那么你需要保持指针 向量。智能指针或原始指针取决于什么 正在使用该向量,以及与之相关的政策 对象的生命周期。根据我的经验,大多数时候, 矢量用于导航,在这种情况下,你应该使用 原始指针。

答案 1 :(得分:1)

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

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

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

它真的归结为你的对象&#39;预期的生命周期范围以及复制对象的效率。 针对您的预期测试用例进行一些分析,并且不要先决定先验的&#39;应该使用哪一个(正如詹姆斯指出的那样可能是过早优化的情况)。

答案 2 :(得分:1)

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

主要原因是它会产生更清晰的代码,对于RAII(http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization)几乎肯定更好,因为编译器生成的代码没有任何泄漏。这里的一些人指出了有效的性能问题,但它们比大多数人想象的要少。

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

答案 3 :(得分:0)

如果您的对象是简单数据,那么第一个选项总是最好的。新内存由向量对象在内部分配和管理,因此您不必担心它。

答案 4 :(得分:0)

  1. 对象矢量。适用于通常按值传递的项目,易于复制。

  2. 原始指针的向量。对于更复杂的对象(那些你不想复制的对象),有效复制,但在某些地方你必须管理这些指针的生命周期。即使您从向量中删除项目时删除,您也必须知道没有悬空。在对象的生命周期在其他地方进行管理并且您知道这些指针仍然有效的情况下,这可能是最好的方法,并且您只是想将它们泵入矢量中以供某些用途,例如:返回更大集合的子集的API可以作为指向这些对象的指针的向量。

  3. 更常见的是shared_ptr已用于此,因为向量拥有一个副本,而提取一个用于读取/使用的人获得另一个副本,因此不会发生生命周期问题。对于unique_ptr,它几乎是一个由向量​​拥有的策略,其主要原因(2)不必在从向量中删除它时手动删除它。向量需要包含在控制它的类中。多年来,shared_ptr的使用已成为一般推荐的构造,当您不为了终身保障的一般安全而存储对象时。