带有对象或带有对象指针的C++容器
C++ container with object or with object pointer
假设许多对象将被放入std::vector容器中,它们可以通过以下两种方式完成:
解决方案1
std::vector<MyObject> objArray;
for(int i=0; i<100; i++)
{
MyObject obj(i);
objArray.push_back(obj);
}
解决方案2
std::vector<boost::shared_ptr<MyObject> > objArray;
for(int i=0; i<100; i++)
{
MyObject *p_obj = new MyObject(i);
objArray.push_back(p_obj);
}
所以我的问题是:当我们从中选择一个解决方案时,是否有一些标准可以遵循?谢谢
在从中选择一个解决方案时,我们是否可以遵循一些标准?
默认情况下,您应该始终选择最简单、最直接的方式。在您的情况下,第一个是我所指的。如果您需要使用boost::shared_ptr
进行动态分配,您就会知道。
通常,我会选择解决方案#1,即vector<MyObject>
。
这比#2(vector<shared_ptr<MyObject>>
)更简单。
使用#1,您可以拥有良好的内存位置,因为MyObject
实例按顺序存储在内存中,这对缓存非常友好(而且非常高效)
相反,在#2中,指针的值按顺序存储在向量中,但指向的对象分散在堆中,因此在这种情况下没有良好的局部性。
但是,一般规则也有例外。例如,如果MyObject
的实例复制起来很重,移动起来又不便宜,我会使用vector<shared_ptr<MyObject>>
选项。在这种情况下,指针语义可能会有所帮助。
无论如何,如果有疑问,请测量当您不确定某些代码的性能时,只需为您拥有的各种选项编写测试代码,并测量执行时间。
还要注意的是,如果使用C++11/14,您仍然可以使用指针语义,但使用的方式比shared_ptr
更高效:事实上,您可以使用std::unique_ptr
。unique_ptr
没有控制块(典型的shared_ptr
),没有ref计数器的互锁递增和递减操作,并且通常比shared_ptr
更快、更精简。如果您不需要共享所有权语义,并且可以使用C++11编译器,那么unique_ptr
是shared_ptr
的一个很好的替代方案。
还要注意,如果为对象使用适当的分配器,则可以使vector<shared_ptr<...>>
的效率略高:不要使用原始new
,而是考虑使用make_shared
。它有一些优点,比如在顺序内存位置中构建控制块和对象,因此与在远离受控对象的堆上创建的控制块相比,您具有更好的内存位置。
选择很简单:
- 如果存储的对象不是多态的,则存储该对象
- 如果对象是多态性的,并且在内部(包装器)处理多态性,则存储该对象
- 否则,存储unique_ptr或shared_ptr是明智的
我避免最后一种情况(除非是实现细节)。
- 如何将带有自定义对象的容器从C++传递到QML
- 使用带有C++对象和标准库容器的插件系统
- 对象 C++ 向量的 STL 容器
- 在容器上移动分配:以前包含的对象的状态
- 删除包含包含动态对象的 STL 容器的智能指针
- 丢失对容器内对象的引用
- 从对象本身的容器中删除对象
- 了解在 C++ 中分配容器时的对象复制
- 存储在一个通用容器中的派生对象.如何避免铸造
- C++是否有一个容器,每个类型最多存储一个对象
- 基于范围的 for 循环将对象移动到另一个容器中?
- 对象内部有大量数据容器,实现更高效的对象交换
- 用于从可能不存在的容器中检索对象的 API 设计
- 创建/向容器添加对象时如何使用构造函数/析构函数
- 用于将任意成员函数应用于对象容器容器的函子
- std::唯一并从对象容器中删除重复项
- 对象容器的性能与指针容器的性能
- 作为类对象容器的静态向量
- 使用复制赋值实现不同对象容器之间的自动化
- 连接两个对象容器,如果已经存在则添加元素