xSKILLby Infirals
Register

C++ for Beginners

0 of 24 notes read 0%

Reading progress is saved to your INFIRALS account. Sign in to keep this note marked as read.

STL basics: vector and string

Functions and library types13 min readLesson 2 of 5

2.1 The standard library saves work

The standard template library (STL) is the part of the C++ standard library built from containers, iterators, and algorithms. You have already used two containers: std::vector and std::string. The <algorithm> header supplies operations such as sorting, searching, and counting.

These pieces work together. A vector provides iterators that mark a range, and an algorithm accepts that range. Learning the range convention lets you use one function with different containers.

cpp
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> scores = {72, 91, 64, 85};
    std::sort(scores.begin(), scores.end());
    for (int score : scores) {
        std::cout << score << "\n";
    }
    return 0;
}

Output

64
72
85
91

2.1.1 Vector operations

std::vector owns a contiguous block of elements and grows as needed. Useful operations include:

  • push_back(value) adds at the end.
  • pop_back() removes the last element.
  • .size() reports the element count, and .empty() tells you whether the count is zero.
  • .front() and .back() read the ends.
  • .at(index) performs a bounds check.
  • .clear() removes every element.

Indexing is fast because the elements sit next to each other. Adding an element can move the whole block to a larger allocation, so references and iterators can be invalidated after growth.

cpp
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> ids = {11, 24, 37, 42, 24};
    auto it = std::find(ids.begin(), ids.end(), 37);
    if (it != ids.end()) {
        std::cout << "Found at index " << (it - ids.begin()) << "\n";
    }
    std::cout << "Count of 24: " << std::count(ids.begin(), ids.end(), 24) << "\n";
    return 0;
}

Output

Found at index 2
Count of 24: 2

2.1.2 Strings as sequences

std::string manages a sequence of characters and provides the operations you expect: concatenation with +, appending with +=, .size(), indexing, .substr(), and .find().

find returns the position of the first match, or std::string::npos when no match exists. Always compare against npos before using the returned position. substr(start, length) creates a new string from part of the original; leaving out the length takes the rest of the string.

C++20 adds starts_with and ends_with for short string tests, and C++23 adds contains. Use them when your compiler and project target the matching standard. find remains available for earlier standards.

cpp
#include <iostream>
#include <string>

int main() {
    std::string first = "C++";
    std::string second = " notes";
    std::string title = first + second;
    title += "!";
    std::cout << title << "\n";
    std::cout << "Length: " << title.size() << "\n";
    std::cout << "First letter: " << title[0] << "\n";
    return 0;
}

Output

C++ notes!
Length: 10
First letter: C

2.1.3 Iterators and range loops

Iterators are values that point into a container. begin() marks the first element, and end() marks one past the last. Algorithms use a half-open range [begin, end). That convention lets an empty range have the same start and end.

Range-based loops hide the iterators: for (const std::string& name : names). Use auto for iterator variables when the type is long or obvious from context. auto it = scores.begin(); is clearer than spelling the full iterator type.

cpp
#include <iostream>
#include <string>

int main() {
    std::string line = "name: Ravi";
    auto pos = line.find(": ");
    if (pos != std::string::npos) {
        std::string value = line.substr(pos + 2);
        std::cout << "Value: " << value << "\n";
    }
    std::cout << "Position: " << pos << "\n";
    return 0;
}

Output

Value: Ravi
Position: 4

2.1.4 Algorithms replace hand-written loops

std::sort orders a range in place. std::find returns an iterator to the first matching value. std::count counts matches. std::accumulate adds values using an initial total.

Algorithm names describe the operation, and a short call can replace a loop that is easy to get wrong. Read the algorithm's requirements before using it, such as the iterator category and whether the range must be sorted.

2.1.5 When things invalidate

A vector's elements are stored in one block. When push_back needs more room, the vector allocates a larger block, copies or moves the elements, and frees the old block. Any iterator, pointer, or reference into the old block no longer refers to a valid element.

Do not hold a reference to an element and then grow the vector. Take the reference after growth, or use an index and look the element up again. The same rule applies when you erase elements while looping; use an algorithm or rebuild the container when the logic is complex.

cpp
#include <iostream>
#include <vector>

int main() {
    std::vector<double> sales = {120.5, 90.0, 150.0};
    double total = 0.0;
    for (const double& sale : sales) {
        total += sale;
    }
    std::cout << "Entries: " << sales.size() << "\n";
    std::cout << "Average: " << total / sales.size() << "\n";
    return 0;
}

Output

Entries: 3
Average: 120.167

2.1.6 Common mistakes

  • Forgetting #include <algorithm> before std::sort or std::find.
  • Passing .size() where an iterator is expected. Algorithms take scores.begin(), scores.end(), not scores.size().
  • Using a returned iterator after the vector has grown or elements have been erased.
  • Using npos with a vector search or end() with a string search. String search returns a position, and vector search returns an iterator.
  • Modifying a string or vector while a range loop is using it.
cpp
#include <iostream>
#include <numeric>
#include <vector>

int main() {
    std::vector<int> pages = {12, 30, 18};
    int total = std::accumulate(pages.begin(), pages.end(), 0);
    std::cout << "Total pages: " << total << "\n";
    return 0;
}

Output

Total pages: 60

2.1.7 Practice

  1. Store five names in a vector, sort them, and print each on its own line.
  2. Read a sentence into a string and count the vowels with a range loop.
  3. Use find to locate a value in a vector and print its index.
  4. Split a "key:value" string at the colon with find and substr.
  5. Compute the average of a vector of prices and read about <iomanip> to control the decimal places.

Interview questions

3 questions from this note. Open one to see the answer; no account needed.

  • 01What is the difference between vector [] and .at()?

    The [] operator does not check the index, so an invalid index causes undefined behavior. The .at() function checks the index and throws std::out_of_range when it is invalid.

  • 02What does std::find return when a value is missing?

    It returns the range's end iterator, so compare the result with the container's end() value, such as ids.end(). A string search reports a missing value as std::string::npos instead.

  • 03Why can vector iterators become invalid after adding an element?

    Growth may allocate a new storage block and move the elements. Iterators and references into the old block then point to memory that the vector no longer uses.