1. Syntax
    1. & and &&, lvalues and rvalues
  2. Input/Output
    1. Input
    2. output
    3. sstream
  3. STL
    1. vector
      1. Include header file
      2. Construct
      3. Access element
      4. Modify elements
      5. Iterate over elements
      6. Time complexity
    2. queue
      1. Include header file
      2. Construct
      3. Access front and back of queue
      4. Enqueue and dequeue
      5. Time complexity
    3. priority_queue
      1. Include header file
      2. Construct
      3. Access the top of the heap
      4. Pop the top element
      5. Custom comparator
      6. Time complexity
    4. stack
      1. Include header file
      2. Construct
      3. Push/Pop
      4. Access the top element of the stack
      5. Time complexity
    5. map, unordered_map
      1. Include header file
      2. Construct
      3. Access element
      4. Insert, modify, and delete elements
      5. Find elements
      6. Erase elements
      7. traverse
      8. Custom comparator (only supported by map)
      9. Time complexity
    6. set, unordered_set
      1. Include header file
      2. Construct
      3. Insertion and modification
      4. Find elements
      5. Erase elements
      6. traverse
      7. Custom comparator (set only)
      8. Time complexity
    7. string
      1. Include header file
      2. Construct
      3. Access and assignment operations
      4. Modification operations
      5. Find operations
      6. String comparison
      7. Substring
      8. Character checking and case conversion
      9. conversion between strings and numbers
      10. Strings and streams
    8. multiset/multimap
      1. Include header file
      2. Construct
      3. Insert elements
      4. Find elements
      5. Erase elements
      6. traverse
      7. Time complexity
    9. tuple
      1. Include header file
      2. Construct
      3. Access element
      4. Modify
      5. Get length
      6. traverse
    10. algorithm
      1. Include header file
      2. sort
      3. min, max
      4. min_element/max_element
      5. reverse
      6. find
      7. count
      8. transform
      9. binary_search
      10. lower_bound/upper_bound
      11. equal_range
      12. next_permutation/prev_permutation
      13. fill
      14. iota
      15. copy / swap / replace / remove / remove_if
      16. set operations
      17. accumulate / all_of / any_of / none_of / for_each
      18. Time complexity
    11. utility
      1. Include header file
      2. pair
        1. Include header file
        2. Construct
        3. Access element
      3. std::move
Cover image for C++

C++

Words 8.6k
Views
Visitors

Timeline

Timeline

2025-10-03

init

2025-10-12

add next_permutation to generate all permutations of a sequence

2025-10-19

add string

This article introduces the core fundamentals of the C++ programming language, including the concepts of lvalues and rvalues, reference types (lvalue references and rvalue references) and their application scenarios. It details standard input/output methods, such as the usage rules of cin, the getline() function for reading strings containing spaces, and the basic usage of output functions. It also explains the functions and common operations of the three classes in the sstream header file (stringstream, istringstream, ostringstream), including techniques such as string splitting, number parsing, and concatenation. In addition, the article summarizes the usage of common containers in the STL (Standard Template Library): vector supports random access, dynamic expansion, and multiple traversal methods, and gives the time complexity of each operation; queue provides FIFO queue operations, all with O(1) complexity; priority_queue implements a max heap by default, supports custom comparators to construct a min heap, and introduces advanced techniques such as lazy deletion. The overall content is aimed at C++ beginners, covering syntax essentials, input/output handling, and STL container practice, helping readers quickly master common functions and precautions.

Syntax

& and &&, lvalues and rvalues

  • Lvalue

    • Has a name and can take its address.

    • Can appear on the left side of an assignment operator.

    • Example:

      123
      int x = 5; // x is an lvaluex = 10;    // Can be assignedint* p = &x; // Can take address
  • Rvalue

    • Temporary objects or literals, no name, cannot take address.

    • Usually appears on the right side of an assignment operator.

    • Example:

      12
      int y = x + 2; // x+2 is an rvalueint z = 42;    // 42 is an rvalue

    Note: rvalues can be bound to rvalue references (&&)

  • Reference types

Referencemeaning
T&Lvalue reference (can only bind to lvalues)
T&&Rvalue reference (can only bind to rvalues)

Example:

123
int a = 5;int &lref = a;   // Lvalue reference, a is an lvalueint &&rref = 5;  // Rvalue reference, 5 is an rvalue
  • Lvalue references can modify lvalues:
1
lref = 10; // a = 10
  • Rvalue references are often used for move semantics:
12
vector<int> v1 = {1,2,3};vector<int> v2 = std::move(v1); // Rvalue references allow moving resources

Input/Output

Input

First, in C++ language, to use standard input, you need to include the header file.

  • cin

cin is the standard input stream object in C++. Below are two uses of cin: reading individually and reading in batches. The principle of cin, simply put, is that there is a buffer. Data entered from the keyboard is first stored in the buffer, and cin can be used to read data from the buffer.

Note 1: cin can continuously read data from the keyboard.

Note 2: cin uses spaces, tabs, and newline characters as delimiters.

Note 3: cin starts reading from the first non-space character and stops reading when it encounters a delimiter.

  • getline()
12
istream& getline (char* s, streamsize n );istream& getline (char* s, streamsize n, char delim );

From the notes on cin, it can also be seen that when the string we need to read contains spaces in the middle, cin will not read the entire string. In this case, the getline() function can be used to solve the problem.

Note 1: When using the getline() function, you need to include the header file.<string>

Note 2: The getline() function reads a line, the read string includes spaces, and ends when a newline character is encountered.

  • getchar()

This function reads a character from the buffer and is often used to determine whether there is a line break.

output

Similarly, in C++ language, to use standard output, you also need to include the header file.<iostream>

On the output side, we mainly introduce one function, which is the most used.coutNote that if outputendlwhen outputting an object, a newline character will be output, similar to\n

sstream

Include header file

1234
#include <sstream>using std::stringstream;using std::istringstream;using std::ostringstream;

Three classes

Class nameFunctionScenario
stringstreamSupports both read and writeGeneral
istringstreamRead-only input streamParse strings
ostringstreamWrite-only output streamConstruct strings

Common operations:

functionFunctionexample
str()Get/Set internal stringss.str("123 456")
clear()Clear stream stateMust be called when reusing
operator>>Extract data (split by whitespace)ss >> x;
operator<<Insert datass << 42;
getline()Read line by linegetline(ss, s)
good()fail()Check stream stateDetermine if parsing succeeded

Note: must call clear when reusing

Example:

Split string

123456789
#include <sstream>using std::stringstream;string s = "apple banana orange";stringstream ss(s);string word;while (ss >> word) {    cout << word << endl;}
PurposeMethodexampleDescriptionCommon pitfalls
Whitespace tokenizationss >> wordss >> w1 >> w2Split by spaces, newlines, and tabsDoes not split on non-whitespace characters such as commas
Custom delimitergetline(ss, word, ',')getline(ss, word, ',');In,Splitmust usegetline>>Cannot customize delimiter
Parse numbersss >> numint x; ss >> x;String numbers → int/doubleNon-numeric input fails the stream; must checkss.fail()
Concatenate stringsoss << valoss << "ID=" << 5;Efficiently construct dynamic stringsAfter output endsoss.str()Only then can the complete content be obtained

STL

vector

Include header file

12
#include <vector>using std::vector;

Construct

123456789101112131415161718
// Empty vectorvector<int> v1;// Specify size, default initialized to 0vector<int> v2(5);  // 5 elements, each 0// Specify size and initial valuevector<int> v3(5, 42);  // 5 elements, each 42// Via initializer_listvector<int> v4 = {1, 2, 3, 4};// Copy another vectorvector<int> v5(v4);// Construct from arrayint arr[] = {10, 20, 30};vector<int> v6(arr, arr + 3);

Access element

  • Returns a reference to the element

  • Access with bounds checking; throws if out of range std::out_of_range exception

123456789
// Access by index (no bounds checking)int a = v[0];// Access via at() (with bounds checking)int b = v.at(1);// Access first and last elementsint first = v.front();int last = v.back();

Modify elements

123456
v[2] = 10;     // Modify the value at index 2v.push_back(5); // Insert element at the endv.pop_back();   // Remove element at the endv.insert(v.begin() + 1, 20); // Insert 20 at index 1v.erase(v.begin() + 2);      // Erase the element at index 2v.clear();                   // Clear all elements

Iterate over elements

1234567891011
// Index iterationfor (size_t i = 0; i < v.size(); ++i)    std::cout << v[i] << " ";// Iterator iterationfor (auto it = v.begin(); it != v.end(); ++it)    std::cout << *it << " ";// Range-based for (C++11+)for (auto &x : v)    std::cout << x << " ";

Time complexity

OperationTime complexityDescription
v[i]O(1)Random access
v.at(i)O(1)Random access with bounds checking
push_back(x)O(1) amortizedAverage constant time, occasional O(n) expansion
pop_back()O(1)Remove element at the end
insert(v.begin() + i, x)O(n)Inserting in the middle, moving n/2 elements on average
erase(v.begin() + i)O(n)Deleting an element in the middle, moving n/2 elements on average
front()/back()O(1)Access first and last elements
size()/empty()O(1)Get size / check if empty
clear()O(n)Clear elements (calls destructors)
sort(v.begin(), v.end())O(n log n)Sort using STL algorithms

queue

Include header file

12
#include <queue>using std::queue;

Construct

12345
// Empty queuequeue<int> q1;// Copy constructorqueue<int> q2(q1);

Access front and back of queue

123
// View front/back elementint front_val = q.front();int back_val  = q.back();

Enqueue and dequeue

123456
// Enqueue (insert at back)q.push(10);q.push(20);// Dequeue (remove from front)q.pop();

Time complexity

OperationTime complexity
push()O(1)
pop()O(1)
front()O(1)
back()O(1)
empty()O(1)
size()O(1)

priority_queue

  • Priority queue, internally uses a max heap by default

  • When dequeuing, always pops the element in the queue that is largest element(default max heap).

  • Custom comparator can be implemented. Min-heap

priority_queue has no iterators; you can only traverse it using pop() and top().

Include header file

12
#include <queue>using std::priority_queue;

Construct

In the template parameters of priority_queue, the first is the type of stored elements, the second is the container for storing elements (defaults to vector), and the third is the comparator for elements.

Note that priority_queue only supports popping the top; it does not support directly modifying or deleting an element in the heap.

  • If you want to delete a priority_element in the queue, consider whether you can use unordered_map implementationLazy deletion(Only delete when an invalid element reaches the top; otherwise, just mark it.)
1234567891011
// Default constructorpriority_queue<int> pq1;// All parameters of the default constructorpriority_queue<int,vector<int>,std::less<int>> pq_full;// Copy constructorpriority_queue<int> pq2(pq1);// Construct from container#include <vector>std::vector<int> v = {1, 3, 2};priority_queue<int> pq3(v.begin(), v.end()); // Default max-heap

Access the top of the heap

12
priority_queue<int> pq;int top_val = pq.top(); // 20

Pop the top element

1
pq.pop();

Custom comparator

Method 1: Use std::greaterImplement a min-heap

1
priority_queue<int, vector<int>, std::greater<int>> min_pq;

Method 2: Custom struct/lambda

1234
struct cmp {    bool operator()(int a, int b) { return a > b; } // Minimum value first};priority_queue<int, vector<int>, cmp> pq_custom;

Method 3: If it is a struct, directly overload the < operator

1234567891011
struct Person {    string name;    int age;    // Overload the < operator    bool operator<(const Person& other) const {        return age < other.age;  // Max heap by default, older age has higher priority.    }};priority_queue<Person> pq;

Time complexity

OperationAverage complexity
pushO(log n)
popO(log n)
topO(1)
sizeO(1)
emptyO(1)

stack

Stack, first in last out

stackNo iterator, cannot useforLoop to traverse directly. Traversal can only be done throughtop()+pop()

Include header file

12
#include <stack>using std::stack;

Construct

12
stack<int> s1;          // Empty stackstack<int> s2(s1);      // Copy constructor

Push/Pop

123456
stack<int> s;// Push (push to top of stack)s.push(20);// Pop (pop the top element)s.pop();

Access the top element of the stack

12
// View the top element of the stackint top_val = s.top();  // Top element of the stack

Time complexity

OperationAverage complexity
pushO(1)
popO(1)
topO(1)
sizeO(1)
emptyO(1)

map, unordered_map

  • map

    • mapYes Ordered associative container, usually implemented with Red-black tree implementation.

    • Each element is key-value pair, key is unique, automatically sorted by key.

    • Suitable for needs access in key order scenarios.

  • unordered_map

    • unordered_mapYes Hash table, unordered storage of key-value.
    • The average time complexity of search, insertion, and deletion is O(1).
    • Suitable for fast lookup,Order doesn’t matter

    GCC’sunordered_mapSince C++11, there is an optimization:

    • When the linked list length in a bucket exceeds a certain threshold (usually 8), the linked list is converted to a red-black tree.
    • This prevents the O(n) complexity caused by worst-case hash collisions, reducing the lookup complexity from O(n) to O(log n).
    • That is:linked list → red-black tree, rather than the entire hash table degenerating into a red-black tree.

Include header file

map

123
// map#include <map>using std::map;

unordered_map

123
// unordered_map#include <unordered_map>using std::unordered_map;

Construct

map

12345678
// empty mapmap<int, string> m1;// Copy constructormap<int, string> m2(m1);// Initializer listmap<int, string> m3 = {{1, "one"}, {2, "two"}};

unordered_map

12345678
// empty tableunordered_map<int, string> um1;// Copy constructorunordered_map<int, string> um2(um1);// Initializer listunordered_map<int, string> um3 = {{1,"one"}, {2,"two"}};

Access element

map

12345
map<int, string> m;// Access elementstring s = m[1];       // The key must exist, otherwise a default value will be created.

unordered_map

1234
unordered_map<int, string> um;// Access elementstring s = m[1];       // The key must exist, otherwise a default value will be created.

Insert, modify, and delete elements

map

123456
map<int, string> m;// Insert elementsm.insert({3, "three"});m[1] = "one";     // Insert or modifym[2] = "two";

unordered_map

123456
unordered_map<int, string> um;// Insertum.insert({3, "three"});um[1] = "one";um[2] = "two";

Find elements

map

123456
map<int, string> m;bool hasKey = um.count(2); // 0 or 1auto it = m.find(2);   // Returns an iterator, or m.end() if not foundbool hasKey = um.count(2); // 0 or 1

unordered_map

1234
unordered_map<int, string> um;auto it = um.find(2);  // Returns an iterator, or um.end() if not foundbool hasKey = um.count(2); // 0 or 1

Erase elements

map

12345
map<int, string> m;// Erase elementsm.erase(1);            // Erase by keym.erase(m.begin());    // Erase by iterator

unordered_map

12345
unordered_map<int, string> um;// Deleteum.erase(1);um.erase(um.begin());    // Erase by iterator

traverse

map

map is traversed in order of key

12345
map<int, string> m;for (auto &[key, value] : m) {    cout << key << " -> " << value << endl;}

unordered_map

Note:unordered_mapis unordered, traversal order is not fixed.

123
for (auto &[key, value] : um) {    cout << key << " -> " << value << endl;}

Custom comparator (only supported by map)

1
map<int, string, std::greater<int>> m; // Descending order by key

Time complexity

map

OperationAverage complexity
Insertion/DeletionO(log n)
LookupO(log n)
traverseO(n)
Access elementO(log n)

unordered_map

OperationAverage complexityWorst-case complexity
InsertO(1)O(n)
LookupO(1)O(n)
DeleteO(1)O(n)
traverseO(n)O(n)

set, unordered_set

  • set
    • setYes Ordered set, usually implemented with Red-black tree implementation.
    • Store Unique elements, automatically sorted by element value.
    • Suitable for needs ordered access and fast lookup of unique elements scenarios.
  • unordered_set
    • unordered_setYes Hash table set, stores unique elements in no particular order.
    • Average search, insertion, and deletion complexity is O(1).
    • Suitable for fast lookup, order is not a concern.

      GCC’sunordered_setalso supports When the linked list length exceeds the threshold, the bucket is treeified., avoiding worst-case O(n).

Include header file

set

12
#include <set>using std::set;

unordered_set

12
#include <unordered_set>using std::unordered_set;

Construct

set

123
set<int> s1;               // empty setset<int> s2(s1);           // Copy constructorset<int> s3 = {1, 2, 3};   // Initializer list

unordered_set

123
unordered_set<int> us1;              // empty setunordered_set<int> us2(us1);         // Copy constructorunordered_set<int> us3 = {1, 2, 3};  // Initializer list

Insertion and modification

set

12345
set<int> s;s.insert(10);  // Insert elementss.insert(20);s.insert(10);  // Duplicate elements are not inserted.

unordered_set

12345
unordered_set<int> us;us.insert(10);us.insert(20);us.insert(10);  // Duplicate elements are not inserted.

Find elements

set

1234
set<int> s = {1,2,3};auto it = s.find(2);   // Returns an iterator; returns s.end() if not found.bool exists = s.count(2); // Returns 0 or 1

unordered_set

1234
unordered_set<int> us = {1,2,3};auto it = us.find(2);   // Returns an iterator; returns us.end() if not found.bool exists = us.count(2); // Returns 0 or 1

Erase elements

set

12
s.erase(2);        // Erase by element values.erase(s.begin()); // Erase by iterator

unordered_set

12
us.erase(2);us.erase(us.begin());

traverse

set

Iterate in ascending order of elements

123
for (auto &val : s) {    cout << val << " ";}

unordered_set

Iteration order is not fixed

123
for (auto &val : us) {    cout << val << " ";}

Custom comparator (set only)

1
set<int, std::greater<int>> s; // Sorted in descending order

Time complexity

set

OperationAverage complexity
Insertion/DeletionO(log n)
LookupO(log n)
traverseO(n)

unordered_set

OperationAverage complexityWorst-case complexity
InsertO(1)O(n)
LookupO(1)O(n)
DeleteO(1)O(n)
traverseO(n)O(n)

string

In the vast majority of modern C++ compilers (such as GCC/Clang/MSVC),std::stringThe implementation is similar to:

  • Internally usesdynamic arrayto store characters
  • automatically maintains the trailing null terminator'\0'(compatible with C-string)
  • eachstringAlso maintainssizeandcapacity

String capacity growth usually followsexponential growth (e.g., doubling), to reduce repeated memory allocations.

Small String Optimization (SSO)

SSO isstd::stringthe core performance optimization technique.

Purpose: reduce heap memory allocations and speed up small string operations.

When the string length is short (usually ≤ 15 characters), many implementations willdirectly store it in a small buffer inside the object, without allocating heap memory.

1
string s = "hello";  // Likely no heap memory allocation (SSO)

Advantages:

  • Avoid frequentnew/delete
  • Improve performance
  • Reduce memory fragmentation

Include header file

12
#include <string>using std::string;

Construct

Construction methodsPrototypeDescriptionexample
Default constructorstring()Create empty stringstring s1; // ""
Copy constructorstring(const string& str)Copy existing stringstring s2(s1);
Move constructionstring(string&& str)Move existing string (since C++11)string s3(std::move(s1));
C stringstring(const char* s)From a\0C string ending withstring s4("hello");
C string + lengthstring(const char* s, size_t n)Take only the first n charactersstring s5("hello world", 5); // "hello"
Repeated characterstring(size_t n, char c)Create a string of n identical charactersstring s6(4, 'a'); // "aaaa"
Range constructiontemplate<class InputIt> string(InputIt first, InputIt last)Initialize with iterator rangevector<char> v{'x','y','z'}; string s7(v.begin(), v.end());
initializer_liststring(std::initializer_list<char> ilist)Initialize with list of characters (C++11)string s8({'a','b','c'}); // "abc"

Default constructor

12
string s1;cout << s1.size(); // 0
  • Common pitfalls: of an empty stringc_str()still valid, returns""

Copy constructor

123
string s2("hello");string s3(s2);cout << s3; // "hello"
  • Performance suggestions: for large strings, prefer to useconst string&pass by reference to avoid copying

Move construction (C++11+)

1
string s4(std::move(s2));
  • Featuress2the contents are moved, and the original object is empty
  • Advantages: avoids copying memory and improves performance

C string construction

12
string s5("hello");string s6("hello world", 5); // "hello"
  • Use case: initialize from a string literal or C-style array
  • Performance suggestions: if the length is known, use the second parameter to avoid unnecessary scanning
  • Common pitfalls: passing a non-\0terminated string, you must specify the length

Repeated character construction

1
string s7(5, 'x'); // "xxxxx"

Range construction (iterators)

12
vector<char> v{'a','b','c'};string s8(v.begin(), v.end()); // "abc"

initializer_list construction (C++11+)

1
string s9({'x','y','z'}); // "xyz"

Access and assignment operations

Subscript accessoperator[]

123
string s = "hello";char c = s[1]; // 'e's[0] = 'H';    // "Hello"
  • Description

    • No bounds checking is performed; out-of-bounds access leads to undefined behavior.

    • After move construction or reallocation, pointers or references to the original characters may be invalidated.

Safe accessat()

12
char c = s.at(1); // 'e's.at(0) = 'H';    // "Hello"
  • Description
    • performs bounds checking and throws when out of boundsstd::out_of_rangeException.

Accessing first and last characters

12345
char f = s.front(); // 'H'char b = s.back();  // 'o's.front() = 'h';s.back()  = '!';    // "hello!"
  • Description
    • Calling when the string is emptyfront()orback()is undefined behavior.
  • Common pitfalls
    • Accessing an empty string triggers UB (undefined behavior).

String assignment: assign()

assign()Yesstd::stringA multi-purpose assignment function with rich overloads:

PrototypeDescriptionexample
string& assign(const string& str)Copy another strings.assign(s2);
string& assign(string&& str)Move another strings.assign(std::move(s2));
string& assign(const string& str, size_t pos, size_t count)Assign from a substring of strs.assign(s2, 1, 3); // take s2[1..3]
string& assign(const char* s)C string assignments.assign("world");
string& assign(const char* s, size_t n)Assign the first n characterss.assign("hello world", 5); // "hello"
string& assign(size_t n, char c)Assign repeated characterss.assign(4, 'x'); // "xxxx"
template<class InputIt> string& assign(InputIt first, InputIt last)Range assignmentvector<char> v{'a','b'}; s.assign(v.begin(), v.end());
string& assign(initializer_list<char> il)List assignment (C++11+)s.assign({'x','y','z'}); // "xyz"

Modification operations

Append: append()

PrototypeDescriptionexample
string& append(const string& str)Append an entire strings.append(s2);
string& append(const string& str, size_t pos, size_t count)Append a substring of strs.append(s2, 1, 3);
string& append(const char* s)Append a C strings.append("world");
string& append(const char* s, size_t n)Append the first n characters of a C strings.append("hello world", 5); // "hello"
string& append(size_t n, char c)Append n identical characterss.append(3, '!'); // "!!!"
template<class InputIt> string& append(InputIt first, InputIt last)Append a rangevector<char> v{'a','b'}; s.append(v.begin(), v.end());
string& push_back(char c)Append a single characters.push_back('x');

Performance suggestions

Optimize concatenation operations — default concatenation is inefficient

12
string s;s.reserve(1000);  // Reserve space in advance to reduce reallocations
  • When modifying frequently, it is recommended to usestd::ostringstreamorstd::string_view

Insert

PrototypeDescriptionexample
string& insert(size_t pos, const string& str)Insert an entire string at poss.insert(2, s2);
string& insert(size_t pos, const string& str, size_t subpos, size_t count)Insert a substring of strs.insert(1, s2, 0, 2);
string& insert(size_t pos, const char* s)Insert a C strings.insert(0, "Hi");
string& insert(size_t pos, const char* s, size_t n)Insert the first n characters of a C strings.insert(0, "Hello World", 5);
string& insert(size_t pos, size_t n, char c)Insert n copies of a characters.insert(3, 4, '*');
iterator insert(const_iterator p, char c)Insert a single characters.insert(s.begin()+1, 'x');
template<class InputIt> void insert(const_iterator p, InputIt first, InputIt last)Insert Intervals.insert(s.begin(), v.begin(), v.end());

Erase

PrototypeDescriptionexample
string& erase(size_t pos = 0, size_t count = npos)Erase count characters starting from poss.erase(2,3);
iterator erase(const_iterator p)Erase the character pointed to by the iterators.erase(s.begin()+1);
iterator erase(const_iterator first, const_iterator last)Erase a ranges.erase(s.begin(), s.begin()+3);

Replace

PrototypeDescriptionexample
string& replace(size_t pos, size_t count, const string& str)Replace count characters starting at pos with strs.replace(0,2,"Hi");
string& replace(size_t pos, size_t count, const string& str, size_t subpos, size_t subcount)Replace with a substring of strs.replace(0,2,s2,1,2);
string& replace(size_t pos, size_t count, const char* s)Replace with a C strings.replace(0,2,"OK");
string& replace(size_t pos, size_t count, const char* s, size_t n)Replace with the first n characters of a C strings.replace(0,2,"Hello World",5);
string& replace(size_t pos, size_t count, size_t n, char c)Replace with n copies of a characters.replace(0,2,3,'*');
iterator replace(const_iterator first, const_iterator last, InputIt first2, InputIt last2)Replace an iterator ranges.replace(s.begin(), s.begin()+2,v.begin(),v.end());

Find operations

Function prototypeDescriptionexample
size_t find(const string& str, size_t pos=0) constFind the first occurrence of a substring starting from poss.find("world"); // 6
size_t find(const char* s, size_t pos=0) constFind C string starting from poss.find("lo"); // 3
size_t find(const char* s, size_t pos, size_t n) constFind the first n characters of the C strings.find("hello world", 0, 5); // find "hello"
size_t find(char c, size_t pos=0) constFind first occurrence of characters.find('o'); // 4
size_t rfind(const string& str, size_t pos=npos) constFind substring from right to lefts.rfind("lo");
size_t rfind(char c, size_t pos=npos) constFind character from right to lefts.rfind('o');
size_t find_first_of(const string& chars, size_t pos=0) constFind first occurrence of any character in the specified sets.find_first_of("aeiou");
size_t find_last_of(const string& chars, size_t pos=npos) constFind last occurrence of any character in the specified sets.find_last_of("aeiou");
size_t find_first_not_of(const string& chars, size_t pos=0) constFind the first position not in the character sets.find_first_not_of("aeiou");
size_t find_last_not_of(const string& chars, size_t pos=npos) constFind the last position not in the character sets.find_last_not_of("aeiou");

String comparison

Function prototypeDescriptionexamplePerformance
int compare(const string& str) constCompare the entire string with strs.compare("hello");O(min(n, m))
int compare(size_t pos, size_t count, const string& str) constCompare substrings[pos, pos+count)with strs.compare(0,2,"he");O(count)
int compare(size_t pos, size_t count, const string& str, size_t subpos, size_t subcount) constCompare substring of s with substring of strs.compare(0,2,s2,1,2);O(subcount)
int compare(const char* s) constCompare with C strings.compare("hello");O(n)
int compare(size_t pos, size_t count, const char* s) constCompare substring with C strings.compare(0,2,"he");O(count)
int compare(size_t pos, size_t count, const char* s, size_t n) constCompare substring with first n characters of C strings.compare(0,2,"hello",2); // "he"O(n)

Return value:

  • Return value < 0 → s < str
  • Return value = 0 → s == str
  • Return value > 0 → s > str

You can also use operators to compare

operatorFunctionexampleReturn typeComparison method
==Determine whether they are equals == "hello"boolCase-sensitive & character-by-character comparison
!=Check if not equals != tboolsame as above
<Lexicographically less than"abc" < "abd"boolCompare by ASCII/Unicode
<=Less than or equal to"abc" <= "abc"boolsame as above
>Lexicographically greater than"dog" > "cat"boolsame as above
>=Greater than or equal to"hi" >= "ha"boolsame as above

Substring

Function prototypeDescriptionexampleReturn valueNotePerformance
string substr(size_t pos = 0, size_t count = npos) constFrom positionposstart, extract a substring of lengthcountsubstrings.substr(2, 4)Returns a new stringpos > size()Throws an exceptionCreates a new string copy; be mindful of performance

Character checking and case conversion

Requires including the C standard library

1
#include <cctype>

Common character checking functions

functionFunctionexample
isalnum(c)Whether it is a letter or digit'A','z','3'
isalpha(c)Whether it is a letter'A','b'
isdigit(c)Whether it is a digit'0'~'9'
islower(c)Whether it is a lowercase letter'a'
isupper(c)Whether it is an uppercase letter'Z'
isspace(c)Whether it is a whitespace character (space/newline/tab)' ','\n','\t'
ispunct(c)Whether it is a punctuation character',' '.' '!'
isxdigit(c)Whether it is a hexadecimal digit'0'~'9','a'~'f'
isprint(c)Whether it is a printable characterordinary character
iscntrl(c)whether it is a control character'\n' '\r'

case conversion functions

functionDescriptionexample
tolower(c)convert character to lowercasetolower('A') → 'a'
toupper(c)convert character to uppercasetoupper('b') → 'B'

these two functionsonly operate on a single character, to process strings, you need to combine withtransform()

123456789
#include <algorithm>#include <cctype>using std::string;int main(){    string s = "HeLLo";	std::transform(s.begin(), s.end(), s.begin(), ::tolower);  // s = "hello"}

::tolowerin::refers toGlobal scope operator, indicating that the<cctype>the global defined intolowerfunction, to avoid confusion with<locale>instd::tolowerconfusion with (the overloaded version that takes a locale parameter).

conversion between strings and numbers

string to integer conversion function table

functionFunction prototypeParameter descriptionreturn value descriptionexample
stoiint stoi(const string& str, size_t* pos = 0, int base = 10);str: input stringpos: returns the number of characters successfully convertedbase: base (2~36)convertedintstoi("123") → 123stoi("1A", nullptr, 16) → 26
stollong stol(const string& str, size_t* pos = 0, int base = 10);same as aboveis converted tolongstol("99999") → 99999L
stolllong long stoll(const string& str, size_t* pos = 0, int base = 10);same as aboveis converted tolong longstoll("1234567890123")

string to floating-point conversion function table

functionFunction prototypeParameter descriptionreturn value descriptionexample
stoffloat stof(const string& str, size_t* pos = 0);str: stringpos: returns the length of parsed charactersconverted tofloatstof("3.14") → 3.14f
stoddouble stod(const string& str, size_t* pos = 0);same as aboveconverted todoublestod("2.71828")
stoldlong double stold(const string& str, size_t* pos = 0);same as aboveconverted tolong doublestold("1.6180339887")

number to string conversion (to_string)

functionFunction prototypeParameter descriptionreturn value descriptionexample
to_stringstring to_string(int value);value: numberReturns the converted stringto_string(42) → "42"
to_stringstring to_string(double value);same as aboveFloat to stringto_string(3.14) → "3.140000"
to_stringstring to_string(long long value);same as aboveSupports long integersto_string(1234567890123)

Return values and exception summary

Casebehavior
Input is not a numberThrowsstd::invalid_argument
Number out of rangeThrowsstd::out_of_range
Automatically removes leading spaces✅ Supported" 123"
Supports signs"-42"" +88"
Supports partial parsing"123abc"→ 123

Strings and streams

Include header file

1234
#include <sstream>using std::stringstream;using std::istringstream;using std::ostringstream;

Three classes

Class nameFunctionScenario
stringstreamSupports both read and writeGeneral
istringstreamRead-only input streamParse strings
ostringstreamWrite-only output streamConstruct strings

Common operations:

functionFunctionexample
str()Get/Set internal stringss.str("123 456")
clear()Clear stream stateMust be called when reusing
operator>>Extract data (split by whitespace)ss >> x;
operator<<Insert datass << 42;
getline()Read line by linegetline(ss, s)
good()fail()Check stream stateDetermine if parsing succeeded

Note: must call clear when reusing

Example:

Split string

12345678910
#include <sstream>using std::stringstream;string s = "apple banana orange";stringstream ss(s);string word;while (ss >> word) {    cout << word << endl;}
PurposeMethodexampleDescriptionCommon pitfalls
Whitespace tokenizationss >> wordss >> w1 >> w2Split by spaces, newlines, and tabsDoes not split on non-whitespace characters such as commas
Custom delimitergetline(ss, word, ',')getline(ss, word, ',');In,Splitmust usegetline>>Cannot customize delimiter
Parse numbersss >> numint x; ss >> x;String numbers → int/doubleNon-numeric input fails the stream; must checkss.fail()
Concatenate stringsoss << valoss << "ID=" << 5;Efficiently construct dynamic stringsAfter output endsoss.str()Only then can the complete content be obtained

multiset/multimap

multiset

  • Element Allows duplicates, automatically sorted by key
  • Underlying usually uses Red-black tree
  • Does not support subscript access, only iterators
  • Suitable for needs Fast lookup and sequential traversal of duplicate elements

multimap<K,V>

  • key Allows duplicates, sorted by key
  • Underlying usually uses Red-black tree
  • Can pass throughequal_rangeFind all elements with a given key

Include header file

1234567
// multiset#include <set>using std::multiset;// multimap#include <map>using std::multimap;

Construct

multiset

123
multiset<int> ms;            // Empty multisetmultiset<int> ms2(ms);        // Copy constructormultiset<int> ms3 = {1,2,2,3}; // Initializer list

multimap

123
multimap<int,string> mm;            // Empty multimapmultimap<int,string> mm2(mm);       // Copy constructormultimap<int,string> mm3 = {{1,"a"},{2,"b"},{2,"c"}}; // Initializer list

Insert elements

1234567
// multisetms.insert(2);ms.insert(2); // Duplicates allowed// multimapmm.insert({2,"b"});mm.insert({2,"c"}); // Keys can be repeated

Find elements

123456789
// multisetauto it = ms.find(2);       // Returns an iterator to the first 2size_t cnt = ms.count(2);   // Number of occurrences of 2// multimapauto range = mm.equal_range(2); // Returns the range of elements with key=2 [first, second)for(auto it = range.first; it != range.second; ++it) {    cout << it->first << " -> " << it->second << endl;}

Erase elements

123456789
// multisetms.erase(2);          // Remove all elements with value 2auto it = ms.find(2);ms.erase(it);         // Remove the element pointed to by a single iterator// multimapmm.erase(2);          // Remove all elements with key=2auto it2 = mm.find(2);mm.erase(it2);        // Remove the element pointed to by a single iterator

traverse

12345678910
// multisetfor(auto &x : ms) {    cout << x << " ";}cout << endl;// multimapfor(auto &[key,value] : mm) {    cout << key << " -> " << value << endl;}

Time complexity

Operationmultiset / multimap
InsertO(log n)
LookupO(log n)
DeleteO(log n)
traverseO(n)

tuple

Include header file

12
#include <tuple>using std::tuple;

Construct

1234
tuple<int,int,int> tp ={1,2,3};auto tp2 = std::make_tuple(1, 2.5, "hi"); // Automatic type deduction

Access element

  • Cannot access like pair, use std::get<0>(tuple)

    Note, here getRequires index to be a constant, a compile-time constant, so it cannot be used to iterate

123
int a = std::get<0>(tp);int b = std::get<1>(tp);int c = std::get<2>(tp);
  • Since C++17, structured bindings can be used, which is more elegant
1
auto [a, b, c] = tp;
  • You can also use std::tie
12
int a, b, c;std::tie(a, b, std::ignore) = tp;

Modify

1
std::get<1>(tp) = 6;

Get length

12
// tuple lengthconstexpr size_t n = std::tuple_size<decltype(tp)>::value; // n=3

traverse

Not commonly used, use structured bindings + fold expressions

1234567
auto tp = make_tuple(1, 2.5, "hi");// Fold expression traversalstd::apply([](auto&&... args) {    ((cout << args << " "), ...);}, tp);

algorithm

Include header file

1
#include <algorithm>

sort

Basic usage

123456
#include <functional> // std::greater<int>vector<int> v={3,2,4};// Sort in non-decreasing order (ascending)std::sort(v.begin(), v.end());// Sort in non-increasing order (descending)std::sort(v.begin(), v.end(),std::greater<int>)

Custom comparator

1234567891011121314151617
struct Person {    string name;    int age;};vector<Person> people = {{"Alice", 25}, {"Bob", 30}, {"Carol", 20}};// Sort by age ascendingstd::sort(people.begin(), people.end(), [](const Person &a, const Person &b){    return a.age < b.age;});// Sort by age descendingstd::sort(people.begin(), people.end(), [](const Person &a, const Person &b){    return a.age > b.age;});

std::sort does not guarantee stability; if you need a stable sort, use std::stable_sort

  • Stable sort: If two elements are equal, their relative order before sorting remains unchanged after sorting.
  • Unstable sort: The relative order of equal elements may be disrupted after sorting.

min, max

Basic usage

1234
int a = 5, b = 10;int mi = std::min(a, b); // mi = 5int ma = std::max(a, b); // ma = 10

Custom comparator

123456789101112131415
struct Person {    std::string name;    int age;};Person p1{"Alice", 25}, p2{"Bob", 30};// Return the one with smaller ageauto youngest = std::min(p1, p2, [](const Person &x, const Person &y){    return x.age < y.age;});auto oldest = std::max(p1, p2, [](const Person &x, const Person &y){    return x.age < y.age;});

Accepts initializer_list (C++11 and above)

12
int x = std::min({3, 1, 4, 2}); // x = 1int y = std::max({3, 1, 4, 2}); // y = 4

min_element/max_element

min_element and max_Iterator returned by element

1234
vector<int> v= {1,2,4,8};// Find minimum/maximum valueint mn = *std::min_element(v.begin(), v.end());int mx = *std::max_element(v.begin(), v.end());

reverse

Reverse an ordered container

12
vector<int> v = {1,2,4,8};std::reverse(v.begin(), v.end());

find

  • Sequentially find the first element in the range equal to the given value, return an iterator. If not found, returnend
12345
vector<int> v = {1, 3, 5, 7};auto it = std::find(v.begin(), v.end(), 5); // it points to 5if(it != v.end()) {    cout << "Found: " << *it << endl;}

count

  • Count the number of occurrences of a value in the range
12
vector<int> v = {1,2,2,3,2};int cnt = std::count(v.begin(), v.end(), 2); // cnt = 3

transform

123456789
// Single-argument transformation (Unary Operation)template<class InputIt, class OutputIt, class UnaryOperation>OutputIt transform(InputIt first, InputIt last, OutputIt d_first, UnaryOperation unary_op);// Two-argument transformation (Binary Operation)template<class InputIt1, class InputIt2, class OutputIt, class BinaryOperation>OutputIt transform(InputIt1 first1, InputIt1 last1, InputIt2 first2,                   OutputIt d_first, BinaryOperation binary_op);

Example:

1
std::transform(s.begin(), s.end(), s.begin(), ::tolower);

Uses Single-argument version(Unary Operation), meaning:

  • Input range:[s.begin(), s.end())
  • Output range start:s.begin()(modify the string in place)
  • Apply the operation to each character:::tolower

::tolowerin::refers toGlobal scope operator, indicating that the<cctype>the global defined intolowerfunction, to avoid confusion with<locale>instd::tolowerconfusion with (the overloaded version that takes a locale parameter).

You can also not usetolower, pass your own processing logic:

123
transform(s.begin(), s.end(), s.begin(), [](char c) {    return c >= 'a' && c <= 'z' ? c - 32 : c;});

two-argument transform

add elements of two arrays

1234567891011121314151617
#include <iostream>#include <vector>#include <algorithm>using namespace std;int main() {    vector<int> a = {1, 2, 3, 4};    vector<int> b = {10, 20, 30, 40};    vector<int> result(a.size());    // result[i] = a[i] + b[i]    transform(a.begin(), a.end(), b.begin(), result.begin(),              [](int x, int y) { return x + y; });    for (int x : result) cout << x << " ";  // Output: 11 22 33 44}
  • Perform binary search on a sorted sequence, returningbool, determine whether it exists
123
vector<int> v = {1,3,5,7};std::sort(v.begin(), v.end());bool found = std::binary_search(v.begin(), v.end(), 5); // true

lower_bound/upper_bound

  • returns an iteratorrequires the sequence to be sorted
  • lower_bound(begin,end,val): returns the first >= val the position of
  • upper_bound(begin,end,val): returns the first > val the position of
123456
vector<int> v = {1,2,2,3,5};auto lb = std::lower_bound(v.begin(), v.end(), 2); // points to the first 2auto ub = std::upper_bound(v.begin(), v.end(), 2); // points to 3int distance = std::distance(std::lower_bound(vec.begin(), vec.end(), startTime),                         std::upper_bound(vec.begin(), vec.end(), endTime));

equal_range

  • Return[lower_bound, upper_bound)a pair of iterators, the range contains all elements equal to the given value
1234
auto range = std::equal_range(v.begin(), v.end(), 2);for(auto it = range.first; it != range.second; ++it) {    cout << *it << " "; // output all 2s}

next_permutation/prev_permutation

Generate the next lexicographic permutation.If the sequence is initially the lexicographically smallest, repeatedly calling it until it returns false generates all permutations.

12345678910111213
#include <iostream>#include <vector>#include <algorithm>int main() {    // v is initially the lexicographically smallest    std::vector<int> v = {1, 2, 3};    do {        for (int x : v) std::cout << x << " ";        std::cout << "\n";    } while (std::next_permutation(v.begin(), v.end()));}

Output:

123456
1 2 31 3 22 1 32 3 13 1 23 2 1
  • also used forgenerate all combinations of length m of numbers in an array
12345678910111213141516171819202122
#include <iostream>#include <vector>#include <algorithm>int main() {    std::vector<int> vec = {1, 2, 3, 4};    int m = 2;    int n = vec.size();    // Initialize the marker array    std::vector<int> select(n, 0);    std::fill(select.end() - m, select.end(), 1); // The last m elements are 1    do {        // Generate combinations based on select        for (int i = 0; i < n; ++i) {            if (select[i]) std::cout << vec[i] << " ";        }        std::cout << "\n";    } while (std::next_permutation(select.begin(), select.end()));}

output

123456
1 21 32 31 42 43 4

You can also use prev_permutation

123456789101112131415161718192021222324252627282930
#include <iostream>#include <vector>#include <algorithm>int main() {    std::vector<int> vec = {1, 2, 3, 4};    int m = 2; // Combination length    int n = vec.size();    // 1. Create the selection marker array    std::vector<int> select(n, 0);    std::fill(select.begin(), select.begin() + m, 1); // The first m are selected    std::vector<std::vector<int>> result;    // 2. Use prev_permutation to generate all combinations    do {        std::vector<int> combo;        for (int i = 0; i < n; ++i) {            if (select[i]) combo.push_back(vec[i]);        }        result.push_back(combo);    } while (std::prev_permutation(select.begin(), select.end()));    // output    for (auto& c : result) {        for (auto x : c) std::cout << x << " ";        std::cout << "\n";    }}

fill

  • fill(begin,end,val): Fill the entire range with the specified value
123456
vector<int> v(5);std::fill(v.begin(), v.end(), 7); // v = {7,7,7,7,7}std::vector<int> select(n, 0);std::fill(select.begin(), select.begin() + m, 1);

iota

  • iota(begin,end,start): Generate a sequence of consecutive integers
123
#include <numeric>vector<int> v(5);std::iota(v.begin(), v.end(), 10); // v = {10,11,12,13,14}

copy / swap / replace / remove / remove_if

  • copy(begin,end,out_it): Copy a range to another container
123
vector<int> src = {1,2,3};vector<int> dst(3);std::copy(src.begin(), src.end(), dst.begin());
  • swap(a,b)/iter_swap(it1,it2): Swap elements
12
std::swap(a,b);std::iter_swap(v.begin(), v.begin()+1);
  • replace(begin,end,old_val,new_val): Replace elements in a range
1
std::replace(v.begin(), v.end(), 2, 5);
  • remove(begin,end,val)/remove_if(begin,end,pred): Logical removal (needs to be combined witherase
12
v.erase(std::remove(v.begin(), v.end(), 5), v.end());v.erase(std::remove_if(v.begin(), v.end(), [](int x){ return x%2==0; }), v.end());

set operations

  • The sequence must be sorted
  • merge(a,b,out): Merge two sorted sequences
  • set_union(a,b,out): Union
  • set_intersection(a,b,out): Intersection
  • set_difference(a,b,out): Difference
  • unique(begin,end): Remove adjacent duplicate elements
12345678
vector<int> a = {1,2,2,3};vector<int> b = {2,3,4};vector<int> out;std::set_union(a.begin(),a.end(),b.begin(),b.end(),std::back_inserter(out));// out = {1,2,2,3,4}a.erase(std::unique(a.begin(),a.end()), a.end()); // Deduplicate a = {1,2,3}

std::unique only removes adjacent duplicate elements. To deduplicate the entire sequence (remove all duplicates), you must sort the sequence first.

accumulate / all_of / any_of / none_of / for_each

  • accumulate(begin,end,init): Sum over a range (or custom operation)
123
#include <numeric>vector<int> v = {1,2,3};int sum = std::accumulate(v.begin(), v.end(), 0); // sum = 6
  • all_of(begin,end,pred)/any_of/none_of: Determine whether range elements satisfy a condition
12
bool all_even = std::all_of(v.begin(), v.end(), [](int x){ return x%2==0; });bool any_even = std::any_of(v.begin(), v.end(), [](int x){ return x%2==0; });
  • for_each(begin,end,f): Range traversal
1
std::for_each(v.begin(), v.end(), [](int &x){ x++; });

Time complexity

algorithmFunctionTime complexityExample code
sortSort (unstable)O(n log n)std::sort(v.begin(), v.end());
stable_sortStable sortO(n log² n)Worst, averageO(n log n)std::stable_sort(v.begin(), v.end());
min / maxMin/max of two numbersO(1)std::min(a,b); std::max(a,b);
min_element / max_elementRange min/max element iteratorO(n)*std::min_element(v.begin(), v.end());
reverseReverse rangeO(n)std::reverse(v.begin(), v.end());
findSequential searchO(n)auto it = std::find(v.begin(),v.end(),5);
countCount occurrencesO(n)std::count(v.begin(),v.end(),2);
binary_searchExists (binary search, requires sorted)O(log n)std::binary_search(v.begin(),v.end(),5);
lower_boundThe first >= val(binary search)O(log n)auto it=std::lower_bound(v.begin(),v.end(),2);
upper_boundThe first > val(binary search)O(log n)auto it=std::upper_bound(v.begin(),v.end(),2);
equal_rangeReturn the range equal to valO(log n)auto r=std::equal_range(v.begin(),v.end(),2);
fillRange assignmentO(n)std::fill(v.begin(), v.end(), 7);
iotaContinuous assignment (requires<numeric>O(n)std::iota(v.begin(),v.end(),10);
copyCopy rangeO(n)std::copy(src.begin(),src.end(),dst.begin());
swap / iter_swapSwap elementsO(1)std::swap(a,b);
replaceReplace specified valueO(n)std::replace(v.begin(),v.end(),2,5);
remove / remove_ifLogical deletion (requireseraseO(n)v.erase(std::remove(v.begin(),v.end(),5),v.end());
uniqueRemove adjacent duplicates (logical deletion)O(n)v.erase(std::unique(v.begin(),v.end()),v.end());
set_unionUnion (requires sorted)O(n+m)std::set_union(a.begin(),a.end(),b.begin(),b.end(),back_inserter(out));
set_intersectionIntersection (requires sorted)O(n+m)std::set_intersection(...);
set_differenceSet difference (requires sorted order)O(n+m)std::set_difference(...);
mergeMerge two sorted sequencesO(n+m)std::merge(a.begin(),a.end(),b.begin(),b.end(),out.begin());
accumulateRange accumulation (requires<numeric>O(n)int sum=std::accumulate(v.begin(),v.end(),0);
all_of / any_of / none_ofRange condition checkO(n)std::all_of(v.begin(),v.end(),[](int x){return x%2==0;});
for_eachIterate and execute functionO(n)std::for_each(v.begin(),v.end(),[](int &x){x++;});

utility

Include header file

1
#include <utility>

pair

Include header file

12
#include <utility>using std::pair;

Construct

123
pair<int,int> p = {1,2};auto p = std::make_pair(1, 2); // Automatic type deduction

Access element

12
int a = p.first;int b = p.second;

std::move

std::move actually converts the parameter t to an rvalue reference type. It itself does not perform any resource copying or releasing, nor does it call constructors or destructors (the actual move operation is completed by the called move constructor/move assignment operator).

1234
template <typename T>typename std::remove_reference<T>::type&& move(T&& t) noexcept {    return static_cast<typename std::remove_reference<T>::type&&>(t);}

Take std::vector as an example:

12
std::vector<int> a = {1, 2, 3};std::vector<int> b = std::move(a);

Here: std::move(a) turns a into an rvalue reference. The compiler will choose vector’s move constructor instead of the copy constructor.
What the move constructor does:

  • It directly “steals” a’s internal pointer and gives it to b.
  • It sets a’s pointer to null to avoid releasing the same memory during destruction.

So in the end: b holds the data {1,2,3}. a becomes empty (size()==0, but it is still a valid object).

Summary: Takeb = std::move(a)as an example (here it is move construction, b is a new object):

  • b takes over a’s internal pointer (i.e., a’s resources are transferred to b)
  • a is placed in a valid but unspecified state (for std::vector, a becomes empty, size()==0, and is still a valid object)
  • When a is destructed, it releases the resources it currently holds (at this time it is empty, so it will not be released repeatedly)
  • There is no need to manually call the destructor.
Loading comments…