1

I'm learning C++ and reading a book, A tour of C++.

In section 9.2.1, this book says

vector<Shape> vs;               # is bad, 
vector<Shape*> vps;             # is better, and
vector<unique_ptr<Shape>> vups; # is OK. 

My question is why "vector<Shape> vs;" is not accepted, and "vector<unique_ptr<Shape>> vups;" is best? Could you clarify it?

Shape class here is a virtual class. In a previous chapter, Circle class and Triangle class had been defined as derived from Shape. Circle class object and Triangle class object are intended to be stored in the container.

Toshihiro
  • 61
  • 1
  • 1
  • 7

1 Answers1

2

The vector container owns every object in it, specifically constructing the object to become part of the vector. Since you cannot construct a Shape to go into the vector, there would be no way to use std::vector<Shape>. Try to insert an object into that vector, it cannot be done.

On the other hand, a pointer to an instance of any class derived from Shape can be converted to a Shape*, and you can copy pointers with no problem. So this is fine:

vector<Shape*> vps;
vps.insert(new Circle());

Similarly, unique_ptrs are polymorphic. So you can construct a unique_ptr<Shape> that points to an instance of a class derived from Shape.

But there is no way you can make a Shape that is an instance of a class derived from Shape. So vector<Shape> is a non-starter.

Another way to see it is to look at what space the vector will allocate. For a vector of Shape*, it will allocate enough space to hold a Shape*, and that can hold a pointer to an instance of a class derived from Shape, no problem.

For a vector of unique_ptr<Shape>, that will allocate enough space to hold a unique_ptr<Shape>, and that can hold a unique pointer to a Shape that points to a class derived from Shape, no problem.

But what happens with vector<Shape>. That allocates enough space to hold a Shape. But what can we do with that if we're trying to store a class derived from Shape? There is nothing at all we can do with that space! Instances of derived classes are typically larger than instances of their base classes, so such a vector would again be useless to us.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278