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 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."
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 << " ";
}