Suppose I have a class A
, and I need a vector
of objects with class A
.
Is it better to use std::vector<A*>
or std::vector<A>
?
I came across some lectures mentioned that the former doesn't require the definition of copy constructor and copy assignment operator; while the latter requires definitions of both. Is this correct?

- 262,606
- 27
- 330
- 524

- 453
- 7
- 16
-
Related: [C++ Vector of Pointers to Objects](http://stackoverflow.com/questions/1361139/c-vector-of-pointers-to-objects?rq=1). – nrussell Jun 19 '15 at 13:55
-
I'm honestly surprised the answers below don't mention it, but since C++11 the *operations* you perform with your vector dictate what copy/move/assignment semantics your object type has to have. IOW, what you *do* with your vector will cast the deciding vote on whether you need support for one/some/all of the above. For trivial example, usage that requires no copy-ctor nor copy-assignment, but *does* require move-insertable [can be seen here](http://ideone.com/GkZZCZ). The [docs for `std::vector`](http://en.cppreference.com/w/cpp/container/vector) mention this, and are worth the read. – WhozCraig Jun 19 '15 at 14:19
4 Answers
The lecture notes are not fully correct: using a vector of A
uses a copy constructor / a copy assignment operator, but if the default implementation provided by the compiler works for you, you are not required to provide your own definition.
The decision to define a copy constructor, an assignment operator, and a destructor is made independently of the decision to place your objects in a container. You define these three when your class allocates its resources manually. Otherwise, default implementations should work.
Back to the main question, the decision to store a pointer vs. an object depends mostly on the semantic of your collection, and on the need to store objects with polymorphic behavior.
If polymorphic behavior is not needed, and creating copies of your objects is relatively inexpensive, using vector<A>
is a better choice, because it lets the container manage resources for you.
If copying is expensive, and you need polymorphic behavior, you need to use pointers. They are not necessarily need to be raw pointers, though: C++ Standard Library provides smart pointers that will deal with cleanup for you, so you wouldn't have to destroy your objects manually.

- 714,442
- 84
- 1,110
- 1,523
Unlike many other modern languages, C++ thrives on value types.
If you store pointers, you have to manage the resulting objects lifetime. Unless you use a unique_ptr
or similar smart pointers, the language won't help you with that. Losing track of objects is leaking : keeping track of them after you have disposed of them is a dangling reference/pointer. Both are very common bugs.
If you store values (or value-like types), and you teach your data how to move itself efficiently, a vector
will store it contiguously in memory.
On modern computers, CPUs are fast, and memory is amazingly slow. A typical computer will have 3 levels of cache in order to try to make memory faster, but if your data is scattered throughout memory (because you used the free store to store the objects), the CPU has little chance to figure out where you are going to access next.
If your data is in a contiguous buffer, not only will one fetch from memory get more than one object, but the CPU will be able to guess that you are going to want the next chunk of memory in the buffer, and pre-fetch it for you.
So the short version is, if your objects are modest in size, use a vector of actual copies of the object. If they are modestly larger, stick the frequently accessed stuff in the object, and the big less frequently accessed part in a vector
within the object, and write an efficient move
semantics. Then store the object itself in a vector
.
There are a few exceptions to this.
First, polymorphism in value types is hard, so you end up using the free store a lot.
Second, some objects end up having their location part of their identity. Vector moves objects around, and the cost of "rehoming" an object can be not worth the bother.
Third, often performance doesn't matter much. So you do what is easy. At the same time, value types are not that hard, and while premature optimization is a bad idea, so is premature deoptimization. Learning how to work with value types and contiguous vectors is important.
Finally, learn the rule of zero. The rule of zero is that objects which manage resources should have their copy/move/assignment/move assignment/destructors carefully written to follow value semantics rules (or blocked). Then objects that use those resource management objects typically do not need to have their move/copy/assignment/move assign/destructors actually written -- they can be left empty, =default
ed, or similar.
And code you don't write tends to have fewer bugs than code you write.

- 262,606
- 27
- 330
- 524
Do you need to check for identity? if yes then use unique_ptr to store them because then you don't need to take care of deleting them later.
Yes you need copy operations because if you store A into the vector, the vector copys the object. With A* the vector only copys the adress ( the pointer )

- 568
- 5
- 15
This is correct and it depends.
Storing pointers in your container gives you additional flexibility, since you don't need these operators or you can have these operators with side effects and / or high cost. The container itself will, at worse, perform copies of the pointers, the cost of which is quite low. In addition, you can store objects of different sizes (instances of different classes in the same inheritance hierarchy comes to mind, especially if they have virtual methods).
On the other hand, storing the objects themselves lower the access overhead, as you won't need to dereference the pointers everytime you access an element. Moreover, it'll improve data locality (thus lower cache misses, page misses…) and reduce memory consumption and fragmentation.
There's no general rule of thumb, there. Small objects with no side effects in their constructors and copy operators are probably better directly in a container that's read often and rarely modified, while large objects with constructors and copy operators that have expensive side effects fit probably better outside of containers that are often modified, resized…
You have to consider your use case and weight the pros and cons of each approach.

- 2,229
- 1
- 12
- 18