› Module 11: Modern C++ (11 / 14 / 17 / 20) › 11.4 Range-based for & Structured Bindings
M O D U L E

Module 11: Modern C++ (11 / 14 / 17 / 20)

Features that make C++ shorter, safer, and faster to write — auto type inference, lambdas, move semantics, and structured bindings.

11.1 auto & Type Inference

The auto keyword tells the compiler to figure out a variable's type automatically from its initializer, cutting down on verbosity — especially with long, complex template types like nested container iterators — while the variable still remains fully, statically typed under the hood with zero runtime overhead.

auto x = 10;                     // int
auto name = string("Sam");       // std::string
auto it = myVector.begin();      // std::vector<int>::iterator

11.2 Lambda Expressions

A lambda is a small, unnamed function you can define inline, right at the point where you need it — extremely useful for short callbacks passed to STL algorithms like sort or for_each.

The [capture] list at the start controls which surrounding variables the lambda is allowed to access, and how — by value ([x]) or by reference ([&x]).

auto f = [x](int y) -> int { return x + y; }; [capture] (params) -> return_type { body }
Figure 11.1 — Anatomy of a lambda expression
auto add = [](int a, int b) { return a + b; };
cout << add(2, 3); // 5

int threshold = 10;
auto isBig = [threshold](int x) { return x > threshold; };
cout << isBig(15); // 1 (true)

11.3 Move Semantics & Rvalue References

Copying large objects, like a big std::string or a massive std::vector, is computationally expensive because it duplicates all of the underlying heap buffers.

Move semantics let the compiler instead transfer ownership of that heap data straight from a temporary or an explicitly "moved-from" object, leaving the original empty but skipping the expensive deep-copy entirely.

std::move doesn't actually move anything by itself — it simply casts an lvalue to an rvalue reference (T&&) to signal "this can safely be moved from."

std::string a = 'Hello World' (owns buffer) pointer transferred, not copied std::string b = std::move(a); a is now empty (moved-from)
Figure 11.2 — Move transfers ownership instead of copying data
string a = "Hello World";
string b = std::move(a); // b steals a's internal heap buffer; a is left empty!
cout << "b: " << b << "\n"; // "Hello World"
cout << "a: " << a << "\n"; // "" (empty)

11.4 Range-based for & Structured Bindings

The range-based for loop, introduced in C++11, iterates over every element of a container without needing an explicit index counter or iterator, making loops shorter, cleaner, and less error-prone.

Structured bindings, introduced in C++17, let you unpack a pair, tuple, or struct directly into named variables in a single line, instead of accessing cryptic members like .first and .second.

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

// Range-based for loop (C++11):
vector<int> nums = {1, 2, 3};
for (int n : nums) {
    cout << n << " ";
}

// Structured Bindings (C++17):
map<string, int> m = {{"a", 1}, {"b", 2}};
for (auto& [key, value] : m) {
    cout << key << "=" << value << " ";
}
MODULE COMPREHENSIVE QUIZ

Module 11 Final Quiz

Test your understanding across all 4 topics of this module with interview-grade questions, tricky edge cases, and code output predictions.

Take Module 11 Final Quiz →
Yukti Mascot