Skip to content
C++ Better Explained
Go back
How to Insert Into a Vector in C++ (insert, emplace, push_back)

How to Insert Into a Vector in C++

Short answer: v.insert(v.begin() + index, value) inserts at a position, and v.push_back(value) adds to the end. The key thing to know: insert takes an iterator, not an index.


Insert at a Specific Position

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {10, 20, 40, 50};

    // insert 30 at index 2
    v.insert(v.begin() + 2, 30);

    for (int n : v) std::cout << n << ' ';
    // 10 20 30 40 50
}

v.begin() + 2 is an iterator pointing at the third slot. The new value goes before that position, and everything from there onward shifts right.

Insert at the Beginning and End

std::vector<int> v = {2, 3, 4};

v.insert(v.begin(), 1);      // front: 1 2 3 4
v.push_back(5);              // back:  1 2 3 4 5
v.insert(v.end(), 6);        // also the back: 1 2 3 4 5 6

Prefer push_back for appending — it is clearer and avoids constructing an iterator. Use insert(v.end(), ...) only when the position is a variable that might happen to be the end.

Inserting at the front is O(n). Every element must shift one place. Doing it in a loop over n items is O(n²), which is fine for 100 elements and painful for 100,000. If you need cheap front insertion, use std::deque.

Want the STL explained properly? The C++ Better Explained Ebook covers vectors, iterators and containers in plain English — 87 pages, just $19.

Insert Multiple Copies

std::vector<int> v = {1, 5};

v.insert(v.begin() + 1, 3, 0);   // three zeros at index 1
// 1 0 0 0 5

Insert a Range from Another Container

std::vector<int> a = {1, 2, 6};
std::vector<int> b = {3, 4, 5};

a.insert(a.begin() + 2, b.begin(), b.end());
// 1 2 3 4 5 6

This is also how you concatenate two vectors — insert the whole of one at the end of the other:

a.insert(a.end(), b.begin(), b.end());

And from an initializer list:

std::vector<int> v = {1, 4};
v.insert(v.begin() + 1, {2, 3});   // 1 2 3 4

insert vs emplace

emplace constructs the object in place from its arguments instead of copying a finished one:

struct Point {
    int x, y;
    Point(int x, int y) : x(x), y(y) {}
};

std::vector<Point> pts;

pts.push_back(Point(1, 2));        // build, then move
pts.emplace_back(1, 2);            // build directly in the vector

pts.insert(pts.begin(), Point(0, 0));
pts.emplace(pts.begin(), 0, 0);    // same, no temporary

For int and other trivial types the difference is nothing. For objects that are expensive to copy, emplace saves a construction. Note emplace_back takes the constructor arguments, not the object.

What insert Returns

It returns an iterator to the newly inserted element — useful when you want to keep working at that spot:

std::vector<int> v = {1, 3};
auto it = v.insert(v.begin() + 1, 2);
std::cout << *it;    // 2

The Iterator Invalidation Trap

This is the bug that bites people:

std::vector<int> v = {1, 2, 3};
auto it = v.begin();

v.insert(v.begin(), 0);   // may reallocate

std::cout << *it;         // UNDEFINED BEHAVIOUR — it is dangling

When a vector runs out of capacity it allocates a bigger block and moves everything across. Every iterator, pointer and reference into the old block becomes invalid. Use the iterator that insert returned, or re-fetch from begin().

Inserting inside a range-based for loop over the same vector is the same mistake in disguise — don’t.

Reserve First When You Know the Size

std::vector<int> v;
v.reserve(1000);           // one allocation instead of ~10

for (int i = 0; i < 1000; ++i) {
    v.push_back(i);
}

reserve allocates capacity without creating elements, so the repeated growth-and-copy cycle never happens. See reserve vs resize for the difference — resize actually creates elements, which is usually not what you want here.

Quick Reference

GoalCodeCost
Add to endv.push_back(x)O(1) amortised
Construct at endv.emplace_back(args...)O(1) amortised
Insert at indexv.insert(v.begin() + i, x)O(n)
Insert at frontv.insert(v.begin(), x)O(n)
Insert n copiesv.insert(pos, n, x)O(n)
Insert a rangev.insert(pos, b.begin(), b.end())O(n)
Concatenatea.insert(a.end(), b.begin(), b.end())O(n)

Take Your C++ Further

If you want vectors, iterators and the STL explained properly instead of looked up function by function, the C++ Better Explained Ebook covers the fundamentals in plain English. Just $19.

👉 Get the C++ Better Explained Ebook — $19


📋

Free Download: The 10 Mistakes Every C++ Beginner Makes

A free 1-page checklist that shows the exact traps that slow down every C++ beginner — so you can avoid them from day one.

🔒 No spam. Unsubscribe anytime.


Share this post on:

Written by

Sahil Bora

Software Engineer. Author and creator of C++ Better Explained.


Previous Post
C++ Input Validation: Handling Bad cin Input Without Crashing
Next Post
How to Read a File Line by Line in C++

Keep Learning