What are the main features added in C++11, C++14, C++17 and C++20?
Standard Headline features C++11 auto, lambdas, move semantics, smart pointers,nullptr, range-basedfor,constexpr,std::threadC++14 std::make_unique, generic lambdasC++17 structured bindings, std::optional,std::string_view,if constexpr, guaranteed copy elisionC++20 concepts, ranges, coroutines, modules, <=>,std::formatC++23 std::expected,std::printDoes
autokeep the reference when initialized from anint&?C++#include <iostream> using namespace std; int main() { int x = 5; int& r = x; auto a = r; auto& b = r; a = 100; b = 7; cout << x << "\n"; }It prints
7.autodrops the reference, soais a copy anda = 100does not touchx.auto& b = r;keeps the reference, sob = 7changesx.The same rule makes
for (auto s : names)copy every string; writeconst auto&.What is a lambda expression in C++?
An anonymous function object written inline, usually to pass to an algorithm:
[capture](parameters) { body }.C++#include <algorithm> #include <cstdlib> #include <iostream> #include <vector> using namespace std; int main() { vector<int> v = {7, -2, 9, 4, -5}; int limit = 5; auto above = count_if(v.begin(), v.end(), [limit](int x) { return x > limit; }); sort(v.begin(), v.end(), [](int a, int b) { return abs(a) < abs(b); }); cout << above << " | "; for (int x : v) cout << x << " "; cout << "\n"; }This prints
2 | -2 4 -5 7 9. The compiler generates a class with anoperator(), and captures become its members. Store a lambda inauto, or instd::functionwhen you need one fixed type.What does a lambda see after
xchanges:[x]or[&x]?C++#include <iostream> using namespace std; int main() { int x = 1; auto byVal = [x]() { return x; }; auto byRef = [&x]() { return x; }; x = 5; cout << byVal() << " " << byRef() << "\n"; }It prints
1 5.[x]stores a copy ofxwhen the lambda is created;[&x]reads the current value.A by-value capture is
constinside the lambda unless you addmutable, and a by-reference capture that outlives the variable dangles. More in the lambdas docs.What are move semantics and rvalue references?
An rvalue reference
T&&binds to temporaries, so a class can define a move constructor that steals a temporary's resources instead of copying them.C++#include <iostream> #include <string> #include <utility> #include <vector> int main() { std::vector<std::string> v; std::string s = "a long string that does not fit in the small buffer"; v.push_back(s); // copy: s keeps its text v.push_back(std::move(s)); // move: v takes s's buffer std::cout << v.size() << " [" << s << "]\n"; }With GCC this prints
2 []. A moved-from object is "valid but unspecified", so do not rely on its value. Mark move constructorsnoexcept, or containers copy instead.What does
std::moveactually do? What is perfect forwarding?std::movemoves nothing: it casts to an rvalue reference so overload resolution picks the move constructor. Perfect forwarding passes an argument on with its original value category: in a templateT&&is a forwarding reference, andstd::forward<T>(arg)restores it.C++#include <iostream> #include <string> #include <utility> using namespace std; void take(const string&) { cout << "lvalue\n"; } void take(string&&) { cout << "rvalue\n"; } template <typename T> void relay(T&& arg) { take(std::forward<T>(arg)); } int main() { string s = "x"; relay(s); relay(string("y")); relay(std::move(s)); }This prints
lvalue,rvalue,rvalue. Withoutstd::forwardall three printlvalue, because a named parameter is an lvalue.How do
std::optionaland structured bindings (C++17) make code clearer?std::optional<T>holds aTor nothing, replacing sentinels like-1. Structured bindings unpack pairs, tuples and structs into named variables.C++#include <iostream> #include <map> #include <optional> #include <string> using namespace std; optional<int> findAge(const map<string, int>& ages, const string& name) { if (auto it = ages.find(name); it != ages.end()) return it->second; return nullopt; } int main() { map<string, int> ages = {{"ana", 31}, {"raj", 27}}; for (const auto& [name, age] : ages) cout << name << ":" << age << " "; cout << "\n"; cout << findAge(ages, "raj").value_or(-1) << " " << findAge(ages, "zoe").has_value() << "\n"; }This prints
ana:31 raj:27and then27 0. Theif (auto it = ...; cond)form, also C++17, keepsitscoped to theif.What is
constexpr, and how is it different fromconst?constmeans the value does not change after initialization, which may happen at runtime.constexprmeans it can be evaluated at compile time; aconstexprfunction is guaranteed to run at compile time only where a constant is required, such as aconstexprvariable,static_assertor an array size.C++#include <iostream> constexpr long long factorial(int n) { return n <= 1 ? 1 : n * factorial(n - 1); } int main() { static_assert(factorial(5) == 120); constexpr auto f10 = factorial(10); int n = 6; std::cout << f10 << " " << factorial(n) << "\n"; }This prints
3628800 720:f10was computed by the compiler,factorial(n)at runtime. C++20 addsconsteval, which must run at compile time. See the constexpr reference.What do concepts, ranges and the spaceship operator in C++20 look like?
These are shown as plain code because this page's runner compiles C++17; use
g++ -std=c++20.#include <compare> #include <concepts> #include <ranges> #include <vector> // Concepts: constrain a template, with readable errors template <std::integral T> T half(T x) { return x / 2; } // Three-way comparison: one defaulted operator gives ==, !=, <, <=, >, >= struct Version { int major, minor; auto operator<=>(const Version&) const = default; }; // Ranges: lazy, composable views instead of iterator pairs std::vector<int> v = {1, 2, 3, 4, 5, 6}; auto squaresOfEvens = v | std::views::filter([](int x) { return x % 2 == 0; }) | std::views::transform([](int x) { return x * x; }); // 4 16 36C++20 also brought coroutines, modules,
std::formatandstd::span.What is the difference between
enumandenum classin C++?An
enum class(C++11) is scoped and strongly typed: its names are writtenStatus::Ok, so two enums can both have anOk, and it never converts tointsilently. A plainenumleaks its names into the surrounding scope and converts implicitly.C++#include <iostream> using namespace std; enum Color { Red, Green, Blue }; // unscoped: names leak, converts to int enum class Status : char { Ok, Failed, Busy }; // scoped, with a chosen underlying type int main() { int c = Blue; // implicit conversion: allowed Status s = Status::Failed; // the name must be qualified // int bad = s; // error: no implicit conversion int code = static_cast<int>(s); cout << c << " " << code << "\n"; }It prints
2 1. Both kinds can fix the underlying type (: char); anenum classdefaults toint, so it can be forward-declared without one. C++20'susing enum Status;brings the names into scope when the qualification gets noisy. See enums.
Modern C++ Interview Questions
auto, lambdas, move semantics, perfect forwarding, constexpr and C++17 and C++20 features.