C++11~20 新特性【八股】

C++11

C++11 是 C++ 语言发展史上最重要的里程碑之一,被称为“现代 C++”的开端。它引入了大量新特性,极大地提升了代码的安全性、可读性和性能。

以下是 C++11 核心新特性的分类总结:

  • 类型推导 auto 和 decltype
  • 右值引用和移动语义
  • lambda
  • 智能指针
  • 并发支持
  • 标准库 array unordered_map unordered_set
  • for-range
  • =delete、=default
  • override、final
  • constexpr
  • using
  • static_assert
  • noexcept
  • enum class

1. 自动类型推导

  • auto:让编译器根据初始化表达式自动推断变量类型,简化了复杂类型(如迭代器、模板返回值)的声明。

    auto it = vec.begin(); // 代替 std::vector<int>::iterator
    
  • decltype:获取表达式的类型,常用于模板编程中推导返回类型。

2. 右值引用与移动语义 (核心性能优化)

  • 右值引用 (&&):区分左值和右值,为移动语义提供基础。
  • std::move:将对象转换为右值引用,触发移动构造/移动赋值,避免不必要的深拷贝。
  • 完美转发 (std::forward):在模板函数中保持参数的原始值类别(左值/右值)。

3. Lambda 表达式

  • 允许在代码中定义匿名函数,极大简化了 STL 算法回调和事件处理。

    std::sort(v.begin(), v.end(), [](int a, int b){ 
        return a > b; 
    });
    
  • 支持捕获列表 [=], [&], [x] 等灵活捕获外部变量。

4. 智能指针与内存管理

  • std::unique_ptr:独占所有权,零开销抽象,替代 auto_ptr
  • std::shared_ptr / std::weak_ptr:引用计数共享所有权,解决循环引用问题。
  • nullptr:专门的空指针常量,解决了 NULL(即 0)在重载决议中的二义性。

5. 并发编程支持

  • std::thread:原生线程类,无需再依赖 POSIX/pthreads。
  • 同步原语std::mutex, std::lock_guard, std::condition_variable
  • 异步任务std::future, std::promise, std::async
  • 原子操作std::atomic 提供无锁线程安全的数据访问。

6. 容器与初始化改进

  • 统一初始化语法 {}:适用于所有类型,包括数组、STL容器、自定义类。

    std::vector<int> v = {1, 2, 3};
    
  • std::initializer_list:支持自定义类接受 {} 初始化。

  • 新容器std::array(固定大小)、std::unordered_map/set(哈希表)、std::tuple

  • 范围 for 循环for (const auto& x : container)

7. 其他重要特性

特性 说明
constexpr 编译期常量计算,可替代部分宏和模板元编程
override / final 显式标记虚函数重写和禁止继承/重写,增强安全性
enum class 强类型枚举,防止隐式转换和命名污染
noexcept 异常规范,帮助编译器优化和移动语义判断
static_assert 编译期断言,改善模板错误信息
可变参数模板 template<typename... Args>,实现类型安全的变参函数
using 别名 替代 typedef,支持模板别名
委托构造函数 构造函数之间可以互相调用,减少重复代码
默认/删除函数 = default / = delete 显式控制特殊成员函数生成

C++14

C++14 通常被视为 C++11 的“增量完善版”,它没有引入像移动语义或 Lambda 那样颠覆性的特性,而是着重于修复 C++11 的痛点、增强泛型编程能力以及提升代码简洁度

以下是 C++14 的核心新特性总结:

  • 函数返回值推导
  • decltype(auto)
  • 变量模板
  • lambda 增强:泛型 lambda、初始化捕获
  • constexpr 函数放宽条件
  • 二进制字面量、数字分隔符
  • 标准库:make_unique、exchange

1. 函数返回值类型推导

  • 自动返回类型:普通函数可以使用 auto 作为返回类型,编译器会根据 return 语句自动推导。

    auto add(int a, int b) { return a + b; } // 返回 int
    
  • 多返回路径:只要所有 return 语句推导出的类型一致即可。

  • ⚠️ 注意:与 C++11 的尾置返回类型 auto f() -> decltype(...) 不同,C++14 的 auto 会剥离引用和顶层 const(如需保留需用 decltype(auto))。

2. decltype(auto)

  • 完美保留表达式的值类别和引用属性,解决了 auto 剥离引用的问题。

    decltype(auto) forward_ref(T&& t) { 
        return std::forward<T>(t); 
    }
    
  • 常用于转发函数和需要精确保持类型的场景。

3. 变量模板

  • 允许对变量进行模板化,此前只有类、函数和别名可以模板化。

    template<typename T>
    constexpr T pi = T(3.1415926535897932385L);
    
    auto x = pi<double>; // 3.14159...
    
  • STL 中的 _v 后缀 trait(如 std::is_same_v)正是基于此特性实现的。

4. Lambda 增强

  • 泛型 Lambda:参数可以使用 auto,使 Lambda 成为真正的泛型可调用对象。

    auto add = [](auto a, auto b) { return a + b; };
    
  • 初始化捕获:允许在捕获列表中创建并初始化新变量(移动捕获终于可行!)。

    auto p = std::make_unique<int>(42);
    auto fn = [p = std::move(p)]() { return *p; }; // C++11 无法做到
    

5. constexpr 放宽

  • C++11 的 constexpr 函数限制极严(只能有一个 return 语句),C++14 大幅放宽:
    • ✅ 允许多条语句、局部变量、循环、条件分支
    • ✅ 允许修改非静态成员变量
    • ❌ 仍不允许:static/thread_local 变量、未初始化的变量、goto、异常处理

6. 二进制字面量与数字分隔符

  • 二进制字面量0b10101100 前缀。

  • 数字分隔符 ':提高可读性,不影响值和类型。

    auto billion = 1'000'000'000;
    auto mask    = 0b1100'0011;
    

7. 标准库改进

特性 说明
std::make_unique 补齐了 C++11 缺失的 unique_ptr 工厂函数
std::exchange 赋新值并返回旧值,简化移动/交换逻辑
std::quoted I/O 流中安全读写带空格的字符串
用户自定义字面量标准化 std::string, std::chrono, std::complex 提供标准 UDL
元组改进 std::tuple_element_t, 按类型访问 get<type>
关联容器透明比较 find() 等支持异构查找,避免不必要的构造

8. 其他小改进

  • [[deprecated]] 属性:标记弃用的函数/类,编译时产生警告。
  • 聚合初始化扩展:有默认成员初始化器的类仍可聚合初始化。
  • 继承构造函数using Base::Base; 真正可用(C++11 存在缺陷)。

C++17

C++17 是继 C++11 之后又一个重大版本,它在三个维度上带来了实质性变革:语法糖大幅简化日常代码标准库补齐关键缺失并行计算正式进入标准

以下是 C++17 核心新特性的分类总结:


1. 语法简化与安全性提升

结构化绑定

解构复合类型到多个变量,告别 std::tie.first/.second

auto [key, value] = *map_iter;
auto [x, y, z] = get_tuple();
if (auto [iter, inserted] = map.insert({k, v}); inserted) { ... }

if constexpr — 编译期条件分支

替代 SFINAE 和标签分发,让模板代码像普通 if 一样可读:

template<typename T>
auto serialize(const T& val) {
    if constexpr (std::is_arithmetic_v<T>)
        return std::to_string(val);
    else
        return val.to_string(); // 非算术类型分支在实例化时被丢弃
}

类模板参数推导

不再需要 make_xxx 辅助函数:

std::pair p(1, "hello");      // std::pair<int, const char*>
std::vector v{1, 2, 3};       // std::vector<int>
std::mutex m;                 // OK

嵌套命名空间简写

namespace A::B::C { }  // 代替 namespace A { namespace B { namespace C { } } }

[[fallthrough]], [[nodiscard]], [[maybe_unused]]

  • [[nodiscard]]:忽略返回值时编译器警告(防止忘记检查错误码)
  • [[fallthrough]]:显式标记 switch case 有意穿透
  • [[maybe_unused]]:抑制未使用变量/参数警告

2. 标准库重磅新增

组件 说明
std::optional 表示"可能有值",替代指针/哨兵值/out参数
std::variant 类型安全的联合体,替代 union + tag
std::any 存储任意类型的单值容器
std::string_view 零拷贝字符串引用,统一 const char* / std::string 接口
std::filesystem 跨平台文件路径、目录遍历、文件操作(原 Boost.Filesystem)
std::parallel 算法 std::sort(exec::par, ...) 等 69 个并行/向量化执行策略
std::shared_mutex 读写锁,多读单写场景性能优于 mutex
std::scoped_lock 同时锁定多个互斥量,自动避免死锁
节点句柄 extract() / insert(node) 在容器间零拷贝移动节点
std::invoke 统一调用可调用对象(函数指针、成员函数、仿函数)

3. 模板与元编程改进

  • 变量模板特化 & 折叠表达式:

    template<typename... Args>
    auto sum(Args&&... args) { return (... + args); } // 左折叠
    
  • std::void_t:SFINAE 检测成员/类型的标准工具

  • 特征 _v / _t 别名全覆盖std::is_same_v, std::remove_reference_t 等,告别 ::value / ::type

  • 非类型模板参数放宽:允许 auto 作为非类型模板参数

  • constexpr Lambda:Lambda 默认可以是 constexpr


4. 其他实用改进

  • 内联变量:头文件中定义全局常量/静态成员不再违反 ODR

    inline constexpr int max_size = 1024; // 头文件中安全定义
    
  • enum class 构造:可从底层类型显式构造

  • 十六进制浮点字面量0x1.2p3

  • __has_include:预处理阶段检测头文件是否存在

  • 动态内存分配对齐支持operator new(size_t, align_val_t)

  • 异常规范纳入类型系统noexcept 成为函数类型的一部分

C++20

四大支柱特性:

  • Concepts(概念与约束):从语言层面约束模板参数类型,彻底解决以往模板报错晦涩冗长的问题,并在编译期提供清晰的类型检查与重载能力。
  • Coroutines(无栈协程):引入原生的异步编程基础设施,通过 co_awaitco_yieldco_return 关键字实现函数的暂停与恢复,极大简化异步 I/O 和生成器编写。
  • Ranges(范围库):革新 STL 算法写法,支持用管道符 | 进行链式流式操作(如过滤、映射),直接操作容器本身而无需显式传递 begin()/end()
  • Modules(模块):替代传统的头文件包含机制(#include),通过 import 实现组件隔离与高效编译,大幅缩短大型项目的编译构建时间。

其他重要实用特性

  • std::format:提供类似 Python 的安全、高效且类型安全的字符串格式化方案,取代 sprintf 和繁琐的 std::stringstream
  • 三向比较运算符(飞船操作符 <=>:编译器可自动生成所有关系运算符(==, !=, <, <=, >, >=),大幅精简自定义类型的比较代码。
  • 增强的常量求值:引入 consteval(强制立即在编译期执行)与 constinit(保证静态初始化),进一步扩展编译期计算边界。
  • 标准库扩展:增加 std::span(零拷贝连续内存视图)、std::jthread(RAII 自动合并与支持协作取消的线程)以及原子等待通知机制。
posted @ 2026-09-08 15:08  光風霽月  阅读(11)  评论(0)    收藏  举报