The constructor of the vector creates the underlying objects on the main stack with the passed in arguments and then copies these objects into its own memory on the heap.

Suboptimal approach for vector creation

class Cat {
    int x;
public:
    Cat(int x) : x(x) {
        std::cout << "Constructor called" << std::endl;
    };
    Cat(const Cat& otherCat) {
        std::cout << "Copy constructor called"  << std::endl;
    }
};

int main() {
    std::vector<Cat> cats({3,3,3}); // works only if constructor is not explicit
    std::vector<Cat> cats1 {Cat(3),Cat(4), Cat(3)};
    return 0;

Leads to many copies.

Constructor called
Constructor called
Constructor called
Copy constructor called
Copy constructor called
Copy constructor called
Constructor called
Constructor called
Constructor called
Copy constructor called
Copy constructor called
Copy constructor called

Performance issues due to resizing and copying

int main() {
    std::vector<Cat> cats;
    cats.push_back(3);
    cats.push_back(3);
    cats.push_back(3);
    return 0;
}

First object gets created and then copied to the vector’s memory. The second time the vector needs to be resized and the existing and new Cat need to copied over.

The STL vector stores its elements as a continous memory block on the heap. If an element gets added and the vector needs to allocate more memory for that, all elements get moved to that new and bigger memory location.

Constructor called
Copy constructor called
Constructor called
Copy constructor called
Copy constructor called
Constructor called
Copy constructor called
Copy constructor called
Copy constructor called

To fix this resizing, the memory should be allocated in advance. Now only the newly instantiated objects get copied once:

int main() {
    std::vector<Cat> cats;
    cats.reserve(3);
    cats.push_back(3);
    cats.push_back(3);
    cats.push_back(3);
    return 0;
}
Constructor called
Copy constructor called
Constructor called
Copy constructor called
Constructor called
Copy constructor called

To get rid of the unnecessary calls to the copy constructor one can use emplace_back instead of push_back. This instantiates the objects directly in the vector’s memory and thus avoids the copy process.

int main() {
    std::vector<Cat> cats;
    cats.reserve(3);
    cats.emplace_back(3);
    cats.emplace_back(3);
    cats.emplace_back(3);
    return 0;
}
Constructor called
Constructor called
Constructor called