将对象存储在矢量中:最好存储对象或指向它的指针
Storing objects in vector: better to store the object or a pointer to it?
我有一些对象在整个应用程序生命周期中都在使用:它们从未被销毁。我将它们存储在矢量中:
declaration:
std::vector<DoubleValue> bidDealIndexes;
construction:
bidDealIndexes(Instrument::InstrumentsCount())
usage:
DoubleValue& v = bidDealIndexes[0];
或者,我可以存储指针:
declaration:
std::vector<DoubleValue*> bidDealIndexes;
construction:
for (int i = 0; i < Instrument::InstrumentsCount(); i++) {
bidDealIndexes.push_back(new DoubleValue());
}
usage:
DoubleValue* v = bidDealIndexes[0];
问题是哪一个更可取?应该避免这两种选择中的一种(或两种)吗?
对象总是首选对象,除非需要,否则应避免使用指针。主要的论点是,一个人不应该毫无理由地使事情复杂化,指针会导致复杂化。在您的示例中,不需要指针。
按值存储
在可能的情况下,将对象直接存储到向量(或其他STL容器)中最好留给基元类型。这是因为每次插入实际上都会创建存储对象的副本。如果存储类对象,例如DoubleValue
类型,则每次push_back
时都会调用复制构造函数。如果复制构造函数很便宜(即类内的存储空间很小,复制构造函数几乎不工作),那么按值存储将使您的生活变得简单。对于更复杂的对象,甚至可能无法按值存储。例如,无法复制iostream
,因此无法将它们放置到向量中。对于具有昂贵的复制构造函数的类,按值存储将减慢执行速度并增加内存占用。
摘要:用于轻量级对象
原始指针存储
随着C++11(以及其他一些第三方库,如boost)的出现,由于跟踪所有权和对象寿命的复杂性,不鼓励通过原始指针进行存储。这是Stack Overflow中充分介绍的另一个主题领域。如果您不能使用C++11,那么在使用原始指针存储时要小心。这可能比按值存储更具性能,并允许存储无法复制的对象类型(如iostream)。
摘要:当智能指针不可用时用于重量级对象
智能指针存储
C++11引入了std::shared_ptr
及其同类形式的智能指针。它们通过引用计数来管理对象的生存期,并遵循RAII(资源获取即初始化)模式。净效果是,从你的角度来看,它们就像原始指针一样工作,但你不必担心:
- 指向已删除对象的指针
- 谁负责删除对象
我不知道shared_ptr
是否最适合您的情况,但智能指针的使用看起来像:
std::vector<std::shared_ptr<DoubleValue> > bigDealIndexes;
bigDealIndexes.push_back(std::shared_ptr<DoubleValue>(new DoubleValue));
std::cout << "Value of first big deal: " << *(bigDealIndexes[0]) << std::endl;
std::cout << "Member 'a': " << bigDealIndexes[0]->a << std::endl;
摘要:使用C++11、boost或类似库时用于重量级对象
在实践中,如果您的对象是POD,并且向量的长度小于几千个项目,则使用将获得更好的性能
std::vector<DoubleValue>
与缓存未命中相比,副本非常便宜。
如果DoubleValue(非常)大或不可压缩,并且矢量也是对象寿命的控制器,则使用
std::vector<std::unique_ptr<DoubleValue>>
如果DoubleValue很大,并且您更喜欢按值样式(您应该这样做),那么您可以考虑使用pimpl习惯用法实现DoubleValue,并使其可复制或可移动,这将允许您将其存储在std::vector中。
如果向量是恒定长度,请考虑使用std::array
否则,请坚持元素的std::vector
。如果必须插入一整批元素,则可能需要在存储元素之前调用reserve()
,以避免多余的复制。
仅供专家使用: 如果对象的移动成本很高,并且管理添加的成员的生存期是其他人的问题(例如,它们在程序结束前一直有效),那么您可以考虑将存储指针作为优化。不过,只有在仔细衡量和考虑后才能考虑。
在c++11中,按值存储肯定是首选。在c++03中,我可能仍然更喜欢按值存储,除非性能测量结果显示这是一个问题。
在c++11中,您正在使用的vector<T>(N)
构造函数已更改为使用值初始化,而不是制作N
副本。
按值存储更简单,在您的情况下可能会表现得更好。如果性能是一个问题,请测量并查看。
编辑:我做了一些粗略的测量,通过值、原始指针和;unique_ptr和by value位居榜首。
- C++ 在堆栈中包含多态属性的类对象存储
- 将对象存储为其基本虚拟类
- 将大型对象存储在无序映射中是否效率低下
- C++:将未知类型的对象存储为成员变量的类
- 按unique_pointer将传递的对象存储在地图中
- 如何将 c++ 类对象存储为数组?
- 将对象存储在 std::map 中
- 是否存在对象存储在其生存期内可能会更改的情况?
- 将不同类型的对象存储在容器中
- 将自定义可绘制对象存储在数组中会导致绘制时出现分割错误
- 我将如何在C++中文件处理对象(存储/导入)
- 将对象存储在C 中的2维Sprite矩阵中
- 将抽象派生类对象存储在基类向量中
- 将任意函数对象存储到类成员容器中,而无需知道其声明签名
- 如何使用向量将类对象存储在超载操作员中
- 适当的方法将对象存储在Std矢量中
- 将向量对象存储在共享指针投掷错误中
- 将多态对象存储在unordered_set中
- 为什么我可以将对象存储在大小不同的数组中
- 返回对象存储在哪里