Skip to content
C++ Better Explained
Go back
How to Use a Vector of Pairs in C++

How to Use a Vector of Pairs in C++

Short answer:

#include <vector>
#include <utility>
#include <string>

std::vector<std::pair<int, std::string>> v;
v.emplace_back(1, "one");
v.push_back({2, "two"});

for (const auto& [num, word] : v) {          // C++17
    std::cout << num << " = " << word << '\n';
}

Creating and Filling

#include <iostream>
#include <vector>
#include <utility>
#include <string>

int main() {
    // initialise directly
    std::vector<std::pair<std::string, int>> scores = {
        {"Ana", 91},
        {"Bo", 78},
        {"Cy", 85}
    };

    // add more
    scores.emplace_back("Dee", 64);        // constructs in place
    scores.push_back({"Eli", 99});         // builds then moves
    scores.push_back(std::make_pair("Fi", 72));

    std::cout << scores.size();            // 6
}

emplace_back is the one to prefer — it passes the arguments straight to the pair’s constructor rather than building a temporary and copying it.

Accessing the Elements

std::pair<std::string, int> p = scores[0];

std::cout << p.first  << '\n';    // Ana
std::cout << p.second << '\n';    // 91

Pairs have no [] or named members beyond first and second — which is exactly their weakness. p.first tells a reader nothing about what it holds, so for anything non-trivial a small struct is clearer:

struct Score { std::string name; int points; };
std::vector<Score> scores;        // scores[0].name — self-documenting

Use pairs for genuinely anonymous two-value groupings; use structs when the fields have meaning worth naming. Sorting a vector of structs is covered in sorting a vector of structs.

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

Iterating Cleanly with Structured Bindings

// C++17 — readable
for (const auto& [name, points] : scores) {
    std::cout << name << ": " << points << '\n';
}

// pre-C++17 — noisier
for (const auto& p : scores) {
    std::cout << p.first << ": " << p.second << '\n';
}

To modify while iterating, drop the const:

for (auto& [name, points] : scores) {
    points += 5;          // bonus for everyone
}

Sorting

By default, std::sort on pairs compares first, then uses second to break ties:

#include <algorithm>

std::sort(scores.begin(), scores.end());     // by name, A-Z

To sort by the second element, supply a comparator:

// by points, lowest first
std::sort(scores.begin(), scores.end(),
          [](const auto& a, const auto& b) { return a.second < b.second; });

// by points, highest first
std::sort(scores.begin(), scores.end(),
          [](const auto& a, const auto& b) { return a.second > b.second; });

A common real-world need is sorting by one field descending and another ascending:

std::sort(scores.begin(), scores.end(),
          [](const auto& a, const auto& b) {
              if (a.second != b.second) return a.second > b.second;  // points desc
              return a.first < b.first;                              // name asc
          });

Searching

// find an exact pair
auto it = std::find(scores.begin(), scores.end(),
                    std::make_pair(std::string("Bo"), 78));

// find by the first element only
auto it2 = std::find_if(scores.begin(), scores.end(),
                        [](const auto& p) { return p.first == "Bo"; });

if (it2 != scores.end()) {
    std::cout << it2->second;
}

Always compare the result against end() before dereferencing — see finding an element in a vector.

Vector of Pairs vs map

vector of pairsstd::map
Lookup by keyO(n)O(log n)
Keeps insertion orderyesno (sorted by key)
Duplicate keysallowednot allowed
Iteration speedfaster (contiguous)slower (node-based)
Memory overheadlowhigher

The rule of thumb: if you look things up by key often, use a map. If you mostly iterate, want duplicates, or need to preserve insertion order, a vector of pairs is both simpler and faster.

Converting Between Them

#include <map>

// map -> vector of pairs (to sort by value)
std::map<std::string, int> m = {{"Ana", 91}, {"Bo", 78}};
std::vector<std::pair<std::string, int>> v(m.begin(), m.end());

// vector of pairs -> map
std::map<std::string, int> m2(v.begin(), v.end());

Copying a map into a vector is the standard way to sort map entries by value, since a map is always ordered by key.

Quick Reference

GoalCode
Declarestd::vector<std::pair<A,B>> v;
Addv.emplace_back(a, b);
Accessv[i].first, v[i].second
Iterate (C++17)for (auto& [a, b] : v)
Sort by firststd::sort(v.begin(), v.end())
Sort by secondstd::sort(..., cmp on .second)
Find by firststd::find_if(...)

Take Your C++ Further

If you want vectors, pairs and the STL explained properly instead of looked up piecemeal, 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
How to Sort a Map by Value in C++
Next Post
C++ Check if File Exists: 3 Reliable Ways (with Examples)

Keep Learning