C++11 New Features: Complete Guide and Reference
C++11 New Features: Complete Guide and Reference
C++11 (formerly C++0x) was a major update that introduced many modern C++ features. This guide provides a comprehensive reference to all C++11 features with examples.
Core Language Features
1. auto Keyword
Automatic type deduction from initializers.
// Before C++11
std::vector<int>::iterator it = vec.begin();
// C++11
auto it = vec.begin();
auto x = 42; // int
auto y = 3.14; // double
auto z = "hello"; // const char*
auto ptr = new int(5); // int*
// With references
auto& ref = x; // int&
const auto& cref = x; // const int&
2. decltype Keyword
Deduces the type of an expression without evaluating it.
int x = 5;
decltype(x) y = 10; // y is int
decltype(x + 3.14) z; // z is double
// Useful in templates
template<typename T, typename U>
auto add(T a, U b) -> decltype(a + b) {
return a + b;
}
3. Trailing Return Types
Specify return type after function parameters.
// C++11
template<typename T, typename U>
auto multiply(T a, U b) -> decltype(a * b) {
return a * b;
}
// Useful for lambdas and complex types
auto func() -> int(*)() {
return nullptr;
}
4. Range-Based For Loop
Iterate over containers and arrays.
std::vector<int> vec = {1, 2, 3, 4, 5};
// By value
for (auto val : vec) {
std::cout << val << " ";
}
// By reference (modify)
for (auto& val : vec) {
val *= 2;
}
// By const reference (read-only)
for (const auto& val : vec) {
std::cout << val << " ";
}
// Works with arrays
int arr[] = {1, 2, 3};
for (auto x : arr) {
std::cout << x << " ";
}
5. Lambda Expressions
Anonymous function objects.
// Basic syntax: [capture](parameters) -> return_type { body }
// Simple lambda
auto add = [](int a, int b) { return a + b; };
int result = add(3, 4); // 7
// With capture
int x = 10;
auto add_x = [x](int a) { return a + x; }; // Capture by value
auto add_x_ref = [&x](int a) { return a + x; }; // Capture by reference
// Capture all by value
auto func1 = [=](int a) { return a + x; };
// Capture all by reference
auto func2 = [&](int a) { x += a; };
// Mutable lambda (can modify captured by-value variables)
auto counter = [count = 0]() mutable { return ++count; };
// Lambda as function parameter
std::vector<int> vec = {1, 2, 3, 4, 5};
std::for_each(vec.begin(), vec.end(), [](int& n) { n *= 2; });
6. Rvalue References and Move Semantics
Efficient transfer of resources.
// Rvalue reference
int&& rref = 42; // Temporary is an rvalue
// Move constructor
class MyClass {
public:
MyClass(MyClass&& other) noexcept // Move constructor
: data_(std::move(other.data_)) {
other.data_ = nullptr;
}
MyClass& operator=(MyClass&& other) noexcept { // Move assignment
if (this != &other) {
delete data_;
data_ = std::move(other.data_);
other.data_ = nullptr;
}
return *this;
}
private:
int* data_;
};
// std::move
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = std::move(vec1); // vec1 is now empty
7. Perfect Forwarding
Forward arguments with their value category preserved.
template<typename T>
void forward_func(T&& arg) {
// Forward with original value category
other_func(std::forward<T>(arg));
}
// Example usage
forward_func(42); // rvalue forwarded as rvalue
int x = 10;
forward_func(x); // lvalue forwarded as lvalue
forward_func(std::move(x)); // rvalue forwarded as rvalue
8. nullptr Keyword
Type-safe null pointer constant.
// Before C++11
int* ptr = NULL; // NULL is typically 0 or (void*)0
// C++11
int* ptr = nullptr; // Type-safe, can't be confused with integers
void func(int* p);
void func(int i);
func(nullptr); // Calls func(int*)
func(0); // Ambiguous - could be int* or int
func(NULL); // Ambiguous
9. Uniform Initialization
Braced initialization syntax.
// Works everywhere
int x{42};
std::vector<int> vec{1, 2, 3, 4, 5};
std::map<std::string, int> m{{"one", 1}, {"two", 2}};
// Prevents narrowing
int y{3.14}; // Error: narrowing conversion
// Class initialization
class MyClass {
public:
MyClass(int a, double b) : a_(a), b_(b) {}
private:
int a_;
double b_;
};
MyClass obj{10, 3.14}; // Direct initialization
10. Initializer Lists
std::initializer_list for constructor and function parameters.
#include <initializer_list>
class Container {
public:
Container(std::initializer_list<int> list) {
for (auto val : list) {
data_.push_back(val);
}
}
private:
std::vector<int> data_;
};
Container c{1, 2, 3, 4, 5}; // Uses initializer_list
// Function with initializer_list
void print(std::initializer_list<int> list) {
for (auto val : list) {
std::cout << val << " ";
}
}
print({1, 2, 3, 4});
11. constexpr Keyword
Compile-time constant expressions.
// Constexpr functions
constexpr int square(int x) {
return x * x;
}
constexpr int result = square(5); // Computed at compile time
int arr[square(3)]; // Array size computed at compile time
// Constexpr variables
constexpr double pi = 3.14159;
constexpr int max_size = 100;
12. static_assert
Compile-time assertions.
static_assert(sizeof(int) == 4, "int must be 4 bytes");
static_assert(sizeof(void*) == 8, "64-bit platform required");
// In templates
template<typename T>
void func() {
static_assert(std::is_integral<T>::value, "T must be integral");
}
13. Strongly Typed Enums (enum class)
Scoped enumerations.
// Old enum (still available)
enum Color { Red, Green, Blue };
int x = Red; // Implicitly converts to int
// C++11 enum class
enum class Color { Red, Green, Blue };
// int x = Color::Red; // Error: no implicit conversion
Color c = Color::Red;
if (c == Color::Green) { /* ... */ }
// With underlying type
enum class Status : uint8_t { Ok, Error, Pending };
// Forward declaration
enum class Status : int; // Can forward declare with underlying type
14. Explicit Conversion Operators
Control implicit conversions.
class MyBool {
public:
explicit operator bool() const { // Explicit conversion
return value_;
}
// Without explicit, could be used in if statements implicitly
private:
bool value_;
};
MyBool mb;
// bool b = mb; // Error: explicit conversion required
bool b = static_cast<bool>(mb); // OK
if (mb) { /* ... */ } // OK: contextually converted
15. Defaulted and Deleted Functions
class MyClass {
public:
// Default constructor
MyClass() = default;
// Delete copy constructor
MyClass(const MyClass&) = delete;
// Delete copy assignment
MyClass& operator=(const MyClass&) = delete;
// Default move constructor
MyClass(MyClass&&) = default;
// Delete function
void func(int) = delete;
void func(double); // Only this overload available
};
MyClass obj;
// MyClass obj2 = obj; // Error: copy constructor deleted
obj.func(3.14); // OK
// obj.func(42); // Error: func(int) deleted
16. Variadic Templates
Templates with variable number of arguments.
// Base case
void print() {
std::cout << std::endl;
}
// Recursive case
template<typename T, typename... Args>
void print(T first, Args... rest) {
std::cout << first << " ";
print(rest...); // Recursive call
}
print(1, 2.5, "hello", 'c'); // Prints: 1 2.5 hello c
// Perfect forwarding with variadic templates
template<typename... Args>
void emplace(Args&&... args) {
// Forward all arguments
construct(std::forward<Args>(args)...);
}
17. Template Aliases
using for type aliases (better than typedef).
// Old way
typedef std::vector<int> IntVec;
typedef void (*FuncPtr)(int);
// C++11 way
using IntVec = std::vector<int>;
using FuncPtr = void(*)(int);
// Works with templates
template<typename T>
using Vec = std::vector<T>;
Vec<int> vec1;
Vec<std::string> vec2;
template<typename T>
using Ptr = T*;
Ptr<int> ptr; // int*
18. override and final Keywords
class Base {
public:
virtual void func() {}
virtual void func2() final {} // Cannot be overridden
};
class Derived : public Base {
public:
void func() override {} // Explicitly overriding
// void func2() {} // Error: func2 is final
};
class FinalDerived final : public Base {
// This class cannot be inherited
};
19. Raw String Literals
// Regular string
std::string path = "C:\\Users\\Name\\file.txt";
// Raw string (no escape sequences needed)
std::string path2 = R"(C:\Users\Name\file.txt)";
// Multi-line raw string
std::string html = R"(
<html>
<body>
<h1>Hello</h1>
</body>
</html>
)";
// Custom delimiter
std::string text = R"delimiter(Some "quoted" text)delimiter";
20. User-Defined Literals
// Define suffix
long double operator"" _km(long double val) {
return val * 1000.0; // Convert km to meters
}
long double operator"" _m(long double val) {
return val;
}
// Usage
long double distance = 5.5_km + 200.0_m; // 5500.0 meters
// String literal
std::string operator"" _s(const char* str, size_t len) {
return std::string(str, len);
}
auto str = "hello"_s; // std::string
Memory and Alignment
21. alignas Specifier
Specify alignment requirements.
// Align to 16-byte boundary
alignas(16) int aligned_int;
// Align to cache line (typically 64 bytes)
alignas(64) char cache_line_data[64];
// Structure alignment
struct alignas(16) AlignedStruct {
int a;
double b;
char c;
};
// Array alignment
alignas(32) int aligned_array[100];
// Variable alignment
alignas(double) int x; // Align to double's alignment requirement
22. alignof Operator
Query alignment requirement of a type.
#include <iostream>
std::cout << alignof(int) << std::endl; // Typically 4
std::cout << alignof(double) << std::endl; // Typically 8
std::cout << alignof(char) << std::endl; // Typically 1
struct MyStruct {
int a;
double b;
};
std::cout << alignof(MyStruct) << std::endl; // Typically 8 (largest member)
// With alignas
struct alignas(32) AlignedStruct {
int a;
};
std::cout << alignof(AlignedStruct) << std::endl; // 32
23. std::aligned_storage and std::aligned_union
#include <type_traits>
// Aligned storage for uninitialized memory
std::aligned_storage<sizeof(int), alignof(int)>::type storage;
int* ptr = new(&storage) int(42);
// Aligned union storage
std::aligned_union<0, int, double, char>::type union_storage;
Standard Library
24. Smart Pointers
std::unique_ptr
#include <memory>
// Exclusive ownership
std::unique_ptr<int> ptr(new int(42));
std::unique_ptr<int> ptr2 = std::make_unique<int>(42); // C++14, but concept from C++11
// Move semantics
std::unique_ptr<int> ptr3 = std::move(ptr); // ptr is now nullptr
// Custom deleter
std::unique_ptr<FILE, decltype(&fclose)> file(fopen("file.txt", "r"), fclose);
// Array specialization
std::unique_ptr<int[]> arr(new int[10]);
arr[0] = 42;
std::shared_ptr
#include <memory>
// Shared ownership
std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
std::shared_ptr<int> ptr2 = ptr1; // Both point to same object
// Reference counting
std::cout << ptr1.use_count() << std::endl; // 2
// Custom deleter
std::shared_ptr<int> ptr3(new int[10], [](int* p) { delete[] p; });
std::weak_ptr
#include <memory>
std::shared_ptr<int> shared = std::make_shared<int>(42);
std::weak_ptr<int> weak = shared;
// Check if object still exists
if (auto locked = weak.lock()) {
std::cout << *locked << std::endl; // Object still exists
} else {
std::cout << "Object destroyed" << std::endl;
}
// Use case: Breaking circular references
25. STL Container Improvements
std::array
#include <array>
std::array<int, 5> arr = {1, 2, 3, 4, 5};
std::cout << arr.size() << std::endl; // 5
std::cout << arr[0] << std::endl; // 1
arr.fill(0); // Fill with zeros
std::forward_list
#include <forward_list>
std::forward_list<int> flist = {1, 2, 3, 4, 5};
flist.push_front(0);
flist.insert_after(flist.begin(), 10);
Unordered Containers
#include <unordered_map>
#include <unordered_set>
std::unordered_map<std::string, int> umap = {
{"one", 1},
{"two", 2},
{"three", 3}
};
std::unordered_set<int> uset = {1, 2, 3, 4, 5};
26. std::tuple
#include <tuple>
// Create tuple
std::tuple<int, double, std::string> t(42, 3.14, "hello");
// Access elements
std::cout << std::get<0>(t) << std::endl; // 42
std::cout << std::get<1>(t) << std::endl; // 3.14
std::cout << std::get<2>(t) << std::endl; // "hello"
// Make tuple
auto t2 = std::make_tuple(1, 2.5, "world");
// Tie (unpack)
int a;
double b;
std::string c;
std::tie(a, b, c) = t;
// Structured bindings (C++17, but tuple from C++11)
27. std::function and std::bind
#include <functional>
// std::function - type-erased function wrapper
std::function<int(int, int)> add = [](int a, int b) { return a + b; };
int result = add(3, 4); // 7
// Store function pointer
int multiply(int a, int b) { return a * b; }
std::function<int(int, int)> mul = multiply;
// std::bind - bind arguments
using namespace std::placeholders;
auto add_10 = std::bind(add, _1, 10);
int result2 = add_10(5); // 15
auto multiply_by = std::bind(multiply, _1, 2);
int result3 = multiply_by(7); // 14
28. Regular Expressions
#include <regex>
std::string text = "Hello, my email is user@example.com";
std::regex email_pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})");
if (std::regex_search(text, email_pattern)) {
std::cout << "Email found!" << std::endl;
}
// Replace
std::string result = std::regex_replace(text, email_pattern, "[EMAIL]");
// Match groups
std::smatch matches;
if (std::regex_search(text, matches, email_pattern)) {
std::cout << "Email: " << matches[0] << std::endl;
}
29. Random Number Generation
#include <random>
// Random engine
std::random_device rd;
std::mt19937 gen(rd());
// Distributions
std::uniform_int_distribution<> dis(1, 6); // Dice
int dice_roll = dis(gen);
std::uniform_real_distribution<> real_dis(0.0, 1.0);
double random_real = real_dis(gen);
std::normal_distribution<> normal_dis(0.0, 1.0);
double normal_value = normal_dis(gen);
30. Chrono Library
#include <chrono>
using namespace std::chrono;
// Time points
auto start = steady_clock::now();
// ... do work ...
auto end = steady_clock::now();
auto duration = duration_cast<milliseconds>(end - start);
std::cout << "Elapsed: " << duration.count() << " ms" << std::endl;
// Durations
seconds sec(5);
milliseconds ms = duration_cast<milliseconds>(sec); // 5000 ms
// System clock
auto now = system_clock::now();
auto time_t = system_clock::to_time_t(now);
std::cout << std::ctime(&time_t) << std::endl;
Concurrency
31. Thread Support Library
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
// Thread
void worker(int id) {
std::cout << "Thread " << id << " working" << std::endl;
}
std::thread t1(worker, 1);
std::thread t2(worker, 2);
t1.join();
t2.join();
// Mutex
std::mutex mtx;
void safe_increment(int& counter) {
std::lock_guard<std::mutex> lock(mtx);
++counter;
}
// Condition variable
std::condition_variable cv;
std::mutex cv_mtx;
bool ready = false;
// Producer
{
std::lock_guard<std::mutex> lock(cv_mtx);
ready = true;
}
cv.notify_one();
// Consumer
std::unique_lock<std::mutex> lock(cv_mtx);
cv.wait(lock, []{ return ready; });
// Future and Promise
std::promise<int> promise;
std::future<int> future = promise.get_future();
std::thread([&promise]() {
promise.set_value(42);
}).detach();
int value = future.get(); // 42
// Async
auto future2 = std::async(std::launch::async, []() {
return 100;
});
int result = future2.get();
32. Atomic Operations
#include <atomic>
std::atomic<int> counter{0};
// Thread-safe operations
counter.fetch_add(1);
counter.store(10);
int value = counter.load();
// Compare and swap
int expected = 5;
counter.compare_exchange_weak(expected, 10);
Other Features
33. Type Traits
#include <type_traits>
// Type checking
static_assert(std::is_integral<int>::value);
static_assert(std::is_floating_point<double>::value);
static_assert(std::is_pointer<int*>::value);
// Type modifications
using IntPtr = std::add_pointer<int>::type; // int*
using IntRef = std::add_lvalue_reference<int>::type; // int&
using IntNoRef = std::remove_reference<int&>::type; // int
// Enable if (SFINAE)
template<typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
func(T val) {
return val * 2;
}
34. Exception Safety Improvements
#include <exception>
// noexcept specifier
void func() noexcept {
// Function guarantees no exceptions
}
// Exception propagation
void may_throw() {
throw std::runtime_error("Error");
}
void wrapper() noexcept {
try {
may_throw();
} catch (...) {
std::terminate(); // Called if exception escapes noexcept function
}
}
35. Attributes
// [[noreturn]]
[[noreturn]] void terminate() {
std::exit(1);
}
// [[deprecated]]
[[deprecated("Use new_func() instead")]]
void old_func() {}
// [[maybe_unused]]
[[maybe_unused]] int unused_var = 42;
36. Local and Unnamed Types as Template Arguments
// Local types as template arguments
void func() {
struct LocalType {
int value;
};
std::vector<LocalType> vec; // OK in C++11
}
// Unnamed types
enum { Red, Green, Blue } color;
std::vector<decltype(color)> vec2; // OK
37. Right Angle Brackets
// Before C++11: space required
std::vector<std::map<int, std::string> > vec; // Note the space
// C++11: no space needed
std::vector<std::map<int, std::string>> vec; // OK
38. Extern Templates
// Prevent instantiation in this translation unit
extern template class std::vector<int>;
// Explicit instantiation in one translation unit
template class std::vector<int>;
39. Inline Namespaces
namespace v1 {
void func() {}
}
inline namespace v2 {
void func() {} // This is the default version
}
// v2::func() is found when calling func()
40. Delegating Constructors
class MyClass {
public:
MyClass(int a) : a_(a), b_(0) {}
// Delegate to another constructor
MyClass() : MyClass(0) {}
MyClass(int a, int b) : MyClass(a) {
b_ = b;
}
private:
int a_, b_;
};
Summary Table
| Feature | Category | Description |
|---|---|---|
auto |
Language | Type deduction |
decltype |
Language | Type querying |
| Range-based for | Language | Container iteration |
| Lambdas | Language | Anonymous functions |
| Rvalue references | Language | Move semantics |
nullptr |
Language | Type-safe null |
| Uniform initialization | Language | Braced init |
constexpr |
Language | Compile-time constants |
enum class |
Language | Scoped enums |
| Variadic templates | Language | Variable templates |
alignas |
Memory | Alignment specifier |
alignof |
Memory | Alignment query |
| Smart pointers | Library | RAII pointers |
std::array |
Library | Fixed-size array |
std::tuple |
Library | Heterogeneous collection |
std::function |
Library | Function wrapper |
| Regex | Library | Regular expressions |
| Chrono | Library | Time utilities |
| Threads | Concurrency | Multithreading |
| Atomics | Concurrency | Lock-free operations |
Migration Tips
- Replace
NULLwithnullptr - Use
autofor iterator types - Prefer range-based for loops
- Use smart pointers instead of raw pointers
- Use
std::arrayinstead of C arrays - Use
enum classfor type-safe enums - Use lambdas for small function objects
- Enable move semantics for resource-owning classes
Compiler Support
Most modern compilers fully support C++11:
- GCC: 4.8+ (full support)
- Clang: 3.3+ (full support)
- MSVC: Visual Studio 2013+ (full support)
Compile with: -std=c++11 (GCC/Clang) or /std:c++11 (MSVC)
This guide covers the major C++11 features. Each feature significantly improved C++’s expressiveness, safety, and performance, making it a truly modern language.