Reputation: 24067
I have objects that I'm using throughout application lifetime: they are never destroyed. I'm storing them in vector:
declaration:
std::vector<DoubleValue> bidDealIndexes;
construction:
bidDealIndexes(Instrument::InstrumentsCount())
usage:
DoubleValue& v = bidDealIndexes[0];
Alternatively I can store pointers:
declaration:
std::vector<DoubleValue*> bidDealIndexes;
construction:
for (int i = 0; i < Instrument::InstrumentsCount(); i++) {
bidDealIndexes.push_back(new DoubleValue());
}
usage:
DoubleValue* v = bidDealIndexes[0];
The question is which is preferable? Should one (or both) of these options should be avoided?
Upvotes: 3
Views: 2018
Reputation: 15334
In c++11, storing by value like you have done would definitely be preferred. In c++03, I would probably still prefer storing by value unless performance measurements showed it to be a problem.
In c++11 the vector<T>(N)
constructor you are using was changed to use value initialization instead of making N
copies.
Storing by value is simpler and will probably perform better in your case. If performance is a concern measure it and see.
Edit: I did some crude measurements comparing by-value, raw-pointers & unique_ptr and by-value came out top.
Upvotes: 0
Reputation: 69882
In practice, if your object is a POD and your vector is less than several thousand items long, you will get better performance by using a
std::vector<DoubleValue>
. Copies are very cheap compared to cache misses.
If DoubleValue is (very) big or noncopyable and the vector is also the controller of the object's lifetime, then use
std::vector<std::unique_ptr<DoubleValue>>
If DoubleValue is big and you would prefer by-value style (you should), then you could consider implementing DoubleValue using the pimpl idiom and making it copyable or moveable which would allow you to store it in a std::vector.
Upvotes: 2
Reputation: 45654
If your vector is constant-length, consider using std::array
instead.
Otherwise, stick to a std::vector
of element. You might want to call reserve()
before storing the elements to avoid superfluous copying, if you have to insert a whole batch of elements.
For experts only: If the objects are expensive to move though, and managing the added members lifetime is somebody elses problem (e.g they stay alive until end of program), then you might consider storing pointers as an optimisation. Still, only consider that after careful measurement and consideration.
Upvotes: 0
Reputation: 4937
Storing an object directly into a vector (or other STL container) is best left to primitive types when possible. This is because each insertion actually creates a copy of the object being stored. If you are storing a class object, such as your DoubleValue
type, then the copy constructor is called each time you push_back
. If the copy constructor is cheap (i.e. there is little storage inside the class and the copy constructor does little or no work), then storage by value will make your life simple. For more complex objects, storage by value may not even be possible. For example, iostream
s cannot be copied, so they cannot be placed into a vector. For classes with expensive copy constructors, storage by value will slow down execution and increase memory footprint.
Summary: Use for lightweight objects
With the advent of C++11 (and some other 3rd party libraries like boost), storage via raw pointer is discouraged due to the complications of tracking ownership and object lifetime. This is a whole other topic area that's been well covered in Stack Overflow. If you cannot use C++11, then take care when storing by raw pointer. This can be more performant than storage by value, and allows for storage of object types that cannot be copied (such as iostreams).
Summary: Use for heavyweight objects when smart pointers are not available
C++11 introduces smart pointers in the form of std::shared_ptr
and their ilk. These manage the lifetime of the object through reference counting and follow the RAII (resource acquisition is initialization) pattern. The net-effect is that from your perspective they work like raw pointers but you don't have to worry about:
I don't know if shared_ptr
is most appropriate in your situation, but the usage of smart pointers looks something like:
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;
Summary: Use for heavyweight objects when using C++11, boost, or a similar library
Upvotes: 2
Reputation: 20993
Objects are always preferred, and pointers should be avoided unless you need them. The main argument is that one should not complicate things without reason, and pointers introduce complication. In your example there is no need for pointers.
Upvotes: 2