Lesson 68
C++11/14/17/20 Features Overview
Covers major features introduced in C++11, C++14, C++17, and C++20 including auto, lambdas, smart pointers, structured bindings, concepts, and coroutines.
Lesson content
What is the C++11/14/17/20 Features Overview?
The C++11/14/17/20 features overview introduces the major improvements added to the C++ language over the past decade. These standards transformed C++ from a powerful but complex language into a more expressive, safer, and easier-to-use programming language.
Before C++11, developers often wrote lengthy, error-prone code for tasks like memory management, loops, and type declarations. Modern C++ introduced features that reduce boilerplate code, improve performance, and make programs easier to read and maintain.
Think of C++ standards as software updates for your phone. Each version adds new features, improves existing ones, and fixes limitations while maintaining compatibility with older code.
Why do new C++ standards exist?
The C++ language evolves to improve programmer productivity, increase code safety, enhance performance, simplify common programming tasks, support modern hardware and software development, and standardize widely used programming techniques.
Real-world use cases
- Desktop applications
- Game engines
- Operating systems
- Embedded systems
- Financial software
- Scientific computing
- Cloud services
- AI and machine learning frameworks
Prerequisites
- Variables and data types
- Functions
- Classes and objects
- Pointers and references
- Templates (basic knowledge)
- Standard Library basics
Evolution of modern C++
- C++11 (2011) — modernization of the language
- C++14 (2014) — refinements and usability improvements
- C++17 (2017) — productivity and cleaner syntax
- C++20 (2020) — major language enhancements and new paradigms
C++11 features
C++11 was the largest update since the original C++ standard.
// auto keyword: the compiler automatically determines a variable's type
auto number = 42;
auto price = 19.99;
auto message = "Hello";
// Range-based for loop
std::vector<int> numbers{1,2,3,4,5};
for (int value : numbers)
{
std::cout << value << " ";
}
// Lambda expressions
auto square = [](int x)
{
return x * x;
};
std::cout << square(5);
// nullptr replaces the old NULL macro
int* ptr = nullptr;The auto keyword reduces typing, eases template programming, and produces cleaner code. Smart pointers were introduced in the memory header, including std::unique_ptr, std::shared_ptr, and std::weak_ptr, which automatically manage dynamically allocated memory. Move semantics reduce unnecessary copying and improve performance by transferring ownership of resources instead of duplicating them.
C++14 features
C++14 focused on improving C++11.
// Generic lambdas: parameter type is automatically deduced
auto print = [](auto value)
{
std::cout << value;
};
// Return type deduction
auto multiply(int a, int b)
{
return a * b;
}
// Binary literals
int mask = 0b101010;
// Digit separators improve readability
long long population = 1'408'526'449;C++17 features
C++17 introduced many productivity improvements.
// Structured bindings: no need to call .first and .second
std::pair<int, std::string> student{1, "Alice"};
auto [id, name] = student;
// if constexpr: compile-time conditional statements
template<typename T>
void print(T value)
{
if constexpr(std::is_integral_v<T>)
std::cout << "Integer";
else
std::cout << "Other";
}
// std::optional: represents an optional value
std::optional<int> age;
if(age)
std::cout << *age;
// std::variant: stores one of several possible types
std::variant<int, double, std::string> value;
// std::filesystem: portable file and directory operations
std::filesystem::exists("data.txt");C++20 features
C++20 is one of the most significant updates in the language's history.
// Concepts: allow templates to specify requirements on their type parameters
template<typename T>
concept Number = std::is_arithmetic_v<T>;
// Ranges: simplify working with collections
for(int value : numbers | std::views::filter([](int x)
{
return x % 2 == 0;
}))
{
std::cout << value;
}
// Three-way comparison (<=>): automatically generates comparison operators
auto operator<=>(const Person&) const = default;Coroutines enable asynchronous programming with simpler syntax, with applications in networking, game engines, web servers, and task scheduling. Modules replace many uses of header files and improve compilation speed by providing a standardized mechanism for sharing code between translation units.
Example 1: auto and range-based for
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> numbers = {1,2,3,4,5};
for(auto value : numbers)
{
cout << value << " ";
}
return 0;
}
// Output: 1 2 3 4 5Example 2: Lambda expression
#include <iostream>
using namespace std;
int main()
{
auto cube = [](int x)
{
return x * x * x;
};
cout << cube(4);
return 0;
}
// Output: 64Example 3: Smart pointer
#include <iostream>
#include <memory>
using namespace std;
int main()
{
unique_ptr<int> value = make_unique<int>(100);
cout << *value;
return 0;
}
// Output: 100Example 4: Structured bindings
#include <iostream>
#include <tuple>
using namespace std;
int main()
{
tuple<int,string,double> student = {101,"Alice",91.5};
auto[id,name,marks] = student;
cout << id << endl;
cout << name << endl;
cout << marks << endl;
return 0;
}
// Output:
// 101
// Alice
// 91.5Example 5: C++20 concepts
#include <concepts>
#include <iostream>
using namespace std;
template<typename T>
concept Number = integral<T>;
void print(Number auto value)
{
cout << value << endl;
}
int main()
{
print(42);
return 0;
}
// Output: 42Common mistakes and pitfalls
- Using raw pointers everywhere. Fix: prefer smart pointers for ownership
- Replacing every type with auto. Fix: use auto only when it improves readability
- Ignoring compiler support. Fix: compile with the appropriate standard flag (e.g., -std=c++20)
- Using C++20 features with a C++17 compiler. Fix: match code to the selected language standard
- Overusing advanced features. Fix: choose the simplest feature that solves the problem
// Wrong
int* ptr = new int(10);
// Missing delete
// Correct
auto ptr = std::make_unique<int>(10);Best practices
- Learn C++11 features thoroughly before moving to newer standards
- Use auto to simplify code, but avoid hiding important types
- Prefer smart pointers over manual memory management
- Use range-based for loops when iterating over containers
- Adopt std::optional instead of sentinel values where appropriate
- Use structured bindings to improve readability
- Enable the latest language standard supported by your project
- Introduce modern features gradually when updating older codebases
When not to use this
Avoid adopting every new language feature simply because it is available. Consider using older language features when maintaining legacy codebases that must compile with older compilers, when working on embedded platforms with limited compiler support, when a newer feature reduces readability for your team, or when project coding standards restrict certain language features. Always balance modern features with maintainability and team familiarity.
Summary
- C++11 introduced modern C++ with features like auto, lambdas, smart pointers, nullptr, and move semantics
- C++14 refined C++11 with generic lambdas, return type deduction, binary literals, and digit separators
- C++17 added structured bindings, if constexpr, std::optional, std::variant, and std::filesystem
- C++20 introduced concepts, ranges, coroutines, modules, and the three-way comparison operator
- Modern C++ improves safety, readability, maintainability, and performance
- Learn features progressively and use them where they make code clearer and safer
Frequently asked questions
Which C++ standard should beginners learn?
Start with modern C++ (C++17 or C++20) while understanding the foundational features introduced in C++11. Many newer standards build on concepts introduced in C++11.
How do I enable a specific C++ standard?
With GCC or Clang, use compiler options such as g++ -std=c++17 main.cpp or g++ -std=c++20 main.cpp.
Is C++20 backward compatible?
Generally, yes. Most C++17 code compiles under C++20, although some deprecated or changed features may require minor updates.
Should I always use the latest C++ standard?
Use the newest standard that your compiler, libraries, and project requirements support. Newer standards provide useful features, but compatibility requirements may influence your choice.
What is the biggest improvement introduced by modern C++?
There is no single answer, but many developers consider smart pointers, move semantics, lambdas, range-based for loops, structured bindings, and concepts among the most impactful additions because they improve safety, expressiveness, and performance.