我有我在整个应用程序生命周期中使用的对象:它们永远不会被破坏。我将它们存储在vector中:
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];
问题是哪个更好?应该避免这些选项中的一个(或两个)吗?
答案 0 :(得分:2)
始终首选对象,除非您需要,否则应避免使用指针。一个主要的论点是,不应该没有理由使事情复杂化,指针引入复杂性。在您的示例中,不需要指针。
答案 1 :(得分:1)
在实践中,如果您的对象是POD并且您的向量长度少于几千个项目,那么使用
可以获得更好的性能std::vector<DoubleValue>
。与缓存未命中相比,副本非常便宜。
如果DoubleValue(非常)大或不可复制并且向量也是对象生命周期的控制器,那么使用
std::vector<std::unique_ptr<DoubleValue>>
如果DoubleValue很大而你更喜欢按值式(你应该),那么你可以考虑使用pimpl习惯用法实现DoubleValue并使其可复制或可移动,这将允许你将它存储在std :: vector中。
答案 2 :(得分:0)
如果您的矢量是恒定长度,请考虑使用std::array
代替
否则,坚持std::vector
元素。如果必须插入整批元素,可能需要在存储元素之前调用reserve()
以避免多余的复制。
仅限专家: 如果移动对象的成本很高,并且管理添加的成员的生命周期是某些问题(例如他们保持活着直到程序结束),然后您可以考虑将指针存储为优化。不过,经过仔细的测量和考虑后才考虑这一点。
答案 3 :(得分:0)
在c ++ 11中,按照你所做的那样存储肯定是首选。在c ++ 03中,我可能仍然希望按值存储,除非性能测量显示它是一个问题。
在c ++ 11中,您使用的vector<T>(N)
构造函数已更改为使用值初始化而不是复制N
。
按值存储更简单,在您的情况下可能会表现更好。如果表现是一个值得考虑的问题,那就看看吧。
修改:我做了一些原始测量,比较by-value,raw-pointers&amp; unique_ptr和按值排名靠前。
答案 4 :(得分:-1)
将对象直接存储到向量(或其他STL容器)中最好留给原始类型(如果可能)。这是因为每次插入实际上都会创建正在存储的对象的副本。如果要存储类对象(例如DoubleValue
类型),则每次push_back
时都会调用复制构造函数。如果复制构造函数很便宜(即类中存储的内容很少而复制构造函数很少或根本没有工作),那么按值存储将使您的生活变得简单。对于更复杂的对象,甚至可能无法按值存储。例如,iostream
s无法复制,因此无法将它们放入向量中。对于具有昂贵的复制构造函数的类,按值存储将减慢执行速度并增加内存占用。
摘要:用于轻量级对象
随着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或类似库时用于重量级对象