C++ std::vector Complete Guide: Usage, Iterators, and Performance

C++ std::vector Complete Guide: Usage, Iterators, and Performance

이 글의 핵심

Practical guide to std::vector—from basics and algorithms to iterator safety and performance tips.

For how dynamic arrays relate to the classic “array vs linked list” discussion in complexity analysis and interviews, see arrays and lists.

Why vectors are better than arrays

// problem with array
int arr[100];// Fixed size, cannot be changed
// arr[100] = 1;// Out of range not checked

// Advantages of vector
vector<int> v;//Automatically adjust size
v.push_back(1);// add dynamically
//v.at(100);// Check range (raise exception)

Basic usage

Declaration and initialization

#include <vector>
using namespace std;

// empty vector
vector<int>v1;

// Specify size
vector<int> v2(10);// 10 initialized to 0

// initialize with value
vector<int> v3(10, 5);// 10 initialized to 5

// initialization list
vector<int> v4 = {1, 2, 3, 4, 5};

// Copy another vector
vector<int> v5 = v4;

Add/delete elements

vector<int> v;

// add at the end
v.push_back(10);
v.push_back(20);
v.push_back(30);
// v = [10, 20, 30]

// remove end
v.pop_back();
// v = [10, 20]

// insert at specific location
v.insert(v.begin() + 1, 15);
// v = [10, 15, 20]

// Delete specific location
v.erase(v.begin() + 1);
// v = [10, 20]

// delete all
v.clear();
// v = []

Access

vector<int> v = {10, 20, 30, 40, 50};

// index access
cout << v[0];// 10 (no range check)
cout << v.at(0);// 10 (range check)

// first/last element
cout << v.front();// 10
cout << v.back();// 50

// size
cout << v.size();// 5

// check if empty
if (v.empty()) {
cout << "empty" << endl;
}

loop

Index based

vector<int> v = {1, 2, 3, 4, 5};

for (int i = 0; i < v.size(); i++) {
cout << v[i] << " ";
}
// read only
for (int x : v) {
cout << x << " ";
}

// editable
for (int& x : v) {
x *= 2;// double each element
}

Iterator

for (auto it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}

Two-dimensional vector

// 2D vector declaration
vector<vector<int>> matrix;

// 3x4 matrix (initialized to 0)
vector<vector<int>> matrix2(3, vector<int>(4, 0));

// value access
matrix2[0][0] = 1;
matrix2[1][2] = 5;

// add row
matrix.push_back({1, 2, 3});
matrix.push_back({4, 5, 6});

// output
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix[i].size(); j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}

STL algorithm

Sort

#include <algorithm>

vector<int> v = {3, 1, 4, 1, 5, 9};

// ascending order
sort(v.begin(), v.end());
// v = [1, 1, 3, 4, 5, 9]

// descending order
sort(v.begin(), v.end(), greater<int>());
// v = [9, 5, 4, 3, 1, 1]
vector<int> v = {1, 2, 3, 4, 5};

// find value
auto it = find(v.begin(), v.end(), 3);
if (it != v.end()) {
cout << "Find: " << *it << endl;
}

// binary search (sorted vector)
bool found = binary_search(v.begin(), v.end(), 3);

Other

vector<int> v = {1, 2, 3, 4, 5};

// reverse order
reverse(v.begin(), v.end());
// v = [5, 4, 3, 2, 1]

// maximum/minimum value
int maxVal = *max_element(v.begin(), v.end());
int minVal = *min_element(v.begin(), v.end());

// total
int sum = accumulate(v.begin(), v.end(), 0);

Common Mistakes

Mistake 1: Receiving size() as int

// ❌ Dangerous code
int n = v.size();
for (int i = n - 1; i >= 0; i--) { // size_t is unsigned!
// ...
}

// ✅ Correct code
for (int i = (int)v.size() - 1; i >= 0; i--) {
// ...
}

Mistake 2: Deleting during iteration

// ❌ Invalid code
for (int i = 0; i < v.size(); i++) {
if (v[i] == target) {
v.erase(v.begin() + i);// Index twist!
}
}

// ✅ Correct code
for (int i = v.size() - 1; i >= 0; i--) {
if (v[i] == target) {
v.erase(v.begin() + i);
}
}

Mistake 3: Out of range

vector<int> v(10);

// ❌ Out of range
v[10] = 1;// Crash (unchecked)

// ✅ Safe method
v.at(10) = 1;// exception occurs

Practical example

Example 1: Student score management system

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;

class ScoreManager {
private:
vector<int> scores;

public:
// add score
void addScore(int score) {
if (score >= 0 && score <= 100) {
scores.push_back(score);
cout << score << "Score added" << endl;
} else {
cout << "Invalid score (0-100)" << endl;
}
}

// calculate average
double getAverage() const {
if (scores.empty()) return 0.0;
return (double)accumulate(scores.begin(), scores.end(), 0) / scores.size();
}

//highest/lowest score
void printMinMax() const {
if (scores.empty()) {
cout << "No score" << endl;
return;
}
cout << "Highest score: " << *max_element(scores.begin(), scores.end()) << endl;
cout << "Minimum score: " << *min_element(scores.begin(), scores.end()) << endl;
}

// score distribution
void printDistribution() const {
vector<int> dist(5, 0);// A, B, C, D, F
for (int score : scores) {
if (score >= 90) dist[0]++;
else if (score >= 80) dist[1]++;
else if (score >= 70) dist[2]++;
else if (score >= 60) dist[3]++;
else dist[4]++;
}

cout << "=== Score distribution ===" << endl;
cout << "A (90-100): " << dist[0] << "name" << endl;
cout << "B (80-89): " << dist[1] << "name" << endl;
cout << "C (70-79): " << dist[2] << "name" << endl;
cout << "D (60-69): " << dist[3] << "name" << endl;
cout << "F (0-59): " << dist[4] << "name" << endl;
}

// Output sorted scores
void printSorted() const {
vector<int> sorted = scores;// copy
sort(sorted.begin(), sorted.end(), greater<int>());// descending order

cout << "=== Score ranking ===" << endl;
for (int i = 0; i < sorted.size(); i++) {
cout << (i + 1) << "etc: " << sorted[i] << "dot" << endl;
}
}
};

int main() {
ScoreManager sm;

// add score
sm.addScore(85);
sm.addScore(92);
sm.addScore(78);
sm.addScore(95);
sm.addScore(88);

// Statistics output
cout << "\nAverage: " << sm.getAverage() << "Point" << endl;
sm.printMinMax();
cout << endl;
sm.printDistribution();
cout << endl;
sm.printSorted();

return 0;
}

Description: This is a student score management system using vector.We have implemented functions frequently used in practice, such as adding scores, calculating averages, highest/lowest scores, score distribution, and ranking.

Example 2: Filtering using dynamic arrays

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// Filter only even numbers
vector<int> filterEven(const vector<int>& numbers) {
vector<int> result;
for (int num : numbers) {
if (num % 2 == 0) {
result.push_back(num);
}
}
return result;
}

// Filter only numbers in the range
vector<int> filterRange(const vector<int>& numbers, int min, int max) {
vector<int> result;
for (int num : numbers) {
if (num >= min && num <= max) {
result.push_back(num);
}
}
return result;
}

// remove duplicates
vector<int> removeDuplicates(vector<int> numbers) {
sort(numbers.begin(), numbers.end());
auto it = unique(numbers.begin(), numbers.end());
numbers.erase(it, numbers.end());
return numbers;
}

// Vector output helper function
void printVector(const string& label, const vector<int>& v) {
cout << label << ": ";
for (int num : v) {
cout << num << " ";
}
cout << endl;
}

int main() {
vector<int> numbers = {5, 2, 8, 1, 9, 3, 7, 2, 5, 8, 4, 6};

printVector("Original", numbers);

// only even numbers
vector<int> evens = filterEven(numbers);
printVector("Even number", evens);

// range 3-7
vector<int> ranged = filterRange(numbers, 3, 7);
printVector("Range 3-7", ranged);

// remove duplicates
vector<int> unique_nums = removeDuplicates(numbers);
printVector("Remove duplicates", unique_nums);

return 0;
}

Description: Various filtering techniques using vectors.This is a pattern often used in practice, such as extracting only elements that meet conditions or removing duplicates.

Example 3: Implementing a game map with 2D vectors

#include <iostream>
#include <vector>
using namespace std;

class GameMap {
private:
vector<vector<char>> map;
int rows, cols;

public:
GameMap(int r, int c) : rows(r), cols(c) {
// initialize empty map ('.' = empty space)
map.resize(rows, vector<char>(cols, '.'));
}

//obstacle placement
void placeObstacle(int r, int c) {
if (isValid(r, c)) {
map[r][c] = '#';
}
}

// Player Placement
void placePlayer(int r, int c) {
if (isValid(r, c) && map[r][c] == '.') {
map[r][c] = 'P';
}
}

// Item placement
void placeItem(int r, int c) {
if (isValid(r, c) && map[r][c] == '.') {
map[r][c] = 'I';
}
}

// map output
void print() const {
cout << "\n=== Game Map ===" << endl;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
cout << map[i][j] << " ";
}
cout << endl;
}
}

// Check whether it is possible to move
bool canMove(int r, int c) const {
return isValid(r, c) && map[r][c] != '#';
}

// player movement
bool movePlayer(int fromR, int fromC, int toR, int toC) {
if (!isValid(fromR, fromC) || !isValid(toR, toC)) {
return false;
}

if (map[fromR][fromC] != 'P') {
cout << "There are no players" << endl;
return false;
}

if (!canMove(toR, toC)) {
cout << "Cannot move" << endl;
return false;
}

// Acquire item
if (map[toR][toC] == 'I') {
cout << "Item acquired!"<< endl;
}

map[fromR][fromC] = '.';
map[toR][toC] = 'P';
return true;}

private:
bool isValid(int r, int c) const {
return r >= 0 && r < rows && c >= 0 && c < cols;
}
};

int main() {
GameMap game(5, 8);

//obstacle placement
game.placeObstacle(1, 2);
game.placeObstacle(1, 3);
game.placeObstacle(2, 3);
game.placeObstacle(3, 5);

// Item placement
game.placeItem(1, 6);
game.placeItem(3, 2);

// Player Placement
game.placePlayer(0, 0);

game.print();

// player movement
cout << "\nPlayer moves: (0,0) -> (0,1)" << endl;
game.movePlayer(0, 0, 0, 1);
game.print();

cout << "\nPlayer moves: (0,1) -> (1,1)" << endl;
game.movePlayer(0, 1, 1, 1);
game.print();

return 0;
}

Description: This is a game map implementation using 2D vectors.You can dynamically adjust its size and freely place obstacles, players, and items.

Frequently occurring problems

Issue 1: reserve() vs resize() confusion

Symptom: Memory is allocated, but an error occurs when accessing it.

Cause: Not understanding the difference between reserve() and resize()

Solution:

// ❌ Invalid code
vector<int> v;
v.reserve(100);// Reserve memory only
v[0] = 10;// error!size() is still 0

// ✅ Correct code (method 1: use resize)
vector<int> v;
v.resize(100);// set size + initialize to 0
v[0] = 10;//OK

// ✅ Correct code (method 2: use push_back)
vector<int> v;
v.reserve(100);// Pre-allocate memory (avoid reallocation)
for (int i = 0; i < 100; i++) {
v.push_back(i);//OK
}

Differences:

  • reserve(n): Only increases capacity (size remains the same)
  • resize(n): Change size (increase capacity if necessary)

Problem 2: Iterator Invalidation

Symptom: Crash when using iterator after modifying vector.

Cause: When a vector is reallocated with push_back, erase, etc., the existing iterator becomes invalid.

Solution:

// ❌ Invalid code
vector<int> v = {1, 2, 3, 4, 5};
auto it = v.begin();
v.push_back(6);// Reallocation may occur
cout << *it;// Crash!it is invalid

// ✅ Correct code (Method 1: Use index)
vector<int> v = {1, 2, 3, 4, 5};
int idx = 0;
v.push_back(6);
cout << v[idx];//OK

// ✅ Correct code (Method 2: Prevent reallocation with reserve)
vector<int> v = {1, 2, 3, 4, 5};
v.reserve(100);// Ensure sufficient space
auto it = v.begin();
v.push_back(6);// no reallocation
cout << *it;//OK

// ❌ Use iterator after erase
vector<int> v = {1, 2, 3, 4, 5};
for (auto it = v.begin(); it != v.end(); it++) {
if (*it == 3) {
v.erase(it);// invalidate it!
// Crash if it++
}
}

// ✅ Correct code
vector<int> v = {1, 2, 3, 4, 5};
for (auto it = v.begin(); it != v.end(); ) {
if (*it == 3) {
it = v.erase(it);// erase returns the next iterator
} else {
it++;
}
}

Issue 3: Poor performance due to unnecessary copying

Symptom: Program slows down when passing vectors to functions

Cause: Copying entire vector due to value passing.

Solution:

// ❌ Slow code (full copy)
void processVector(vector<int> v) { // Copy occurs!
for (int x : v) {
cout << x << " ";
}
}

int main() {
vector<int> v(1000000);// 1 million
processVector(v);// 1 million full copies!
}

// ✅ Fast code (const reference)
void processVector(const vector<int>& v) { // no copy
for (int x : v) {
cout << x << " ";
}
}

// ✅ If modifications are needed (reference)
void modifyVector(vector<int>& v) { // no copy
for (int& x : v) {
x *= 2;
}
}

// ✅ Transfer of ownership (move)
vector<int> createLargeVector() {
vector<int> v(1000000);
// ... initialize ...
return v;// no copy with move semantics
}

Performance Comparison:

// Benchmark example
vector<int> v(1000000);

// Value passing: ~10ms (copy cost)
// const reference: ~0.001ms (no copy)
// About 10,000 times difference!

Performance optimization

Optimization strategy

  1. Choose an efficient data structure
  • How to apply: Use STL container appropriate for the situation
  • Effect: Improved time complexity
  1. Prevent unnecessary copying
  • How to apply: Use passing by reference
  • Effect: Reduced memory usage
  1. Compiler optimization
  • How to apply: Use -O2, -O3 flags
  • Effect: Increased execution speed

Benchmark results

methodRunning timememory usageRemarks
Basic implementation100ms10 MB-
Optimization 180ms8 MBpassing by reference
Optimization 250ms5 MBSTL algorithm

Conclusion: Performance can be improved by more than 2x with proper optimization

FAQ

Q1: Can even beginners learn?

A: Yes, this guide is written for beginners.Knowing basic C++ syntax is enough.

Q2: Is it often used in practice?

A: Yes, it is used very often.This is an essential concept in practical projects.

Q3: How does it compare to other languages?

A: The advantage of C++ is performance and control.Faster than Python and more flexible than Java.

Q4: How long does learning take?

A: 1-2 hours for basic concepts, 1-2 weeks for mastery.

A:

  1. Learn basic grammar
  2. Follow a simple example
  3. Application of practical projects
  4. Learn advanced techniques

Q6: What are some common mistakes you make?

A:

  • Do not reset
  • Memory management mistakes
  • Does not consider time complexity
  • Missing exception handling

Good article to read together (internal link)

Here’s another article related to this topic.

  • C++ string |“String processing” complete guide [Summary of practical functions]
  • C++ set/unordered_set |“The Complete Guide to Deduplication”
  • C++ map/unordered_map |Complete summary of “Hash Map” [Performance comparison]

Practical tips

These are tips that can be applied right away in practice.

Debugging tips

  • If you run into a problem, check the compiler warnings first.
  • Reproduce the problem with a simple test case

Performance Tips

  • Don’t optimize without profiling
  • Set measurable indicators first

Code review tips

  • Often used in code reviewsCheck the receiving part in advance
  • Follow your team’s coding conventions

Practical checklist

This is what you need to check when applying this concept in practice.

Before writing code

  • Is this technique the best way to solve the current problem?
  • Can team members understand and maintain this code?
  • Does it meet the performance requirements?

Writing code

  • Have you resolved all compiler warnings?
  • Have you considered edge cases?
  • Is error handling appropriate?

When reviewing code

  • Is the intent of the code clear?
  • Are there enough test cases?
  • Is it documented?

Use this checklist to reduce mistakes and improve code quality.


Keywords covered in this article (related search terms)

This article will be helpful if you search for C++, STL, vector, vector, array, container, etc.


  • C++ vector vs list vs deque |
  • C++ array vs vector |