7

I am wondering if you can store items into a vector, using the emplace_back, a type that is derived from the class that vector expects.

For example:

struct fruit
{
    std::string name;
    std::string color;
};

struct apple : fruit
{
    apple() : fruit("Apple", "Red") { }
};

Somewhere else:

std::vector<fruit> fruits;

I want to store an object of type apple inside the vector. Is this possible?

Walter
  • 44,150
  • 20
  • 113
  • 196
TheAJ
  • 10,485
  • 11
  • 38
  • 57

2 Answers2

12

No. A vector only stores elements of a fixed type. You want a pointer to an object:

#include <memory>
#include <vector>

typedef std::vector<std::unique_ptr<fruit>> fruit_vector;

fruit_vector fruits;
fruits.emplace_back(new apple);
fruits.emplace_back(new lemon);
fruits.emplace_back(new berry);
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Thanks for the quick response. I have a small question though, say I create a local unique_ptr to store the object from the fruit_vector, wouldn't the memory at the address be deleted when that local unique_ptr goes out of scope? – TheAJ Jan 20 '13 at 01:38
  • 2
    @TheAJ: Well, that's the whole point, right? If you want to keep the object, transfer the pointer to the container... – Kerrek SB Jan 20 '13 at 01:46
  • More elegant way in C++14 would be: `fruits.emplace_back(std::make_unique());` – Maciej S Nov 14 '17 at 14:21
  • @MaciejS: No, you'd use `push_back` in that case. – Kerrek SB Nov 14 '17 at 19:26
  • @KerrekSB: Why? https://stackoverflow.com/questions/29089227/push-back-or-emplace-back-with-stdmake-unique – Maciej S Nov 15 '17 at 08:41
  • @MaciejS: Use push_back when it works, and emplace_back when you have to. The purpose of emplace is to use explicit constructors, and if you don't have to do that, you can use a more appropriate tool. – Kerrek SB Nov 15 '17 at 21:51
  • @MaciejS: Basically, if you already have an object of the right type, use push_back. If you want to *construct* an object from constructor arguments, use emplacement. – Kerrek SB Nov 15 '17 at 21:58
  • @KerrekSB Yes, but this isn't the only benefit to using `emplace_back()` it also returns a reference to the newly created element, which is a reason to prefer the method suggested by @MaciejS – j b Sep 19 '18 at 18:11
  • 1
    @JamieBullock: Not in C++11 (see question tag) :-) – Kerrek SB Sep 19 '18 at 23:10
2

std::vector<fruit> fruits; It only stores fruit in fruits not derived types as allocator only allocates sizeof(fruit) for each element. To keep polymorphism, you need to store pointer in fruits.

std::vector<std::unique_ptr<fruit>> fruits;
fruits.emplace_back(new apple);

apple is dynamically allocated on free store, will be release when element is erased from vector.

fruits.erase(fruits.begin());
Walter
  • 44,150
  • 20
  • 113
  • 196
billz
  • 44,644
  • 9
  • 83
  • 100