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作为非类型模板参数 -
constexprLambda: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_await、co_yield、co_return关键字实现函数的暂停与恢复,极大简化异步 I/O 和生成器编写。 - Ranges(范围库):革新 STL 算法写法,支持用管道符
|进行链式流式操作(如过滤、映射),直接操作容器本身而无需显式传递begin()/end()。 - Modules(模块):替代传统的头文件包含机制(
#include),通过import实现组件隔离与高效编译,大幅缩短大型项目的编译构建时间。
其他重要实用特性:
std::format:提供类似 Python 的安全、高效且类型安全的字符串格式化方案,取代sprintf和繁琐的std::stringstream。- 三向比较运算符(飞船操作符
<=>):编译器可自动生成所有关系运算符(==,!=,<,<=,>,>=),大幅精简自定义类型的比较代码。 - 增强的常量求值:引入
consteval(强制立即在编译期执行)与constinit(保证静态初始化),进一步扩展编译期计算边界。 - 标准库扩展:增加
std::span(零拷贝连续内存视图)、std::jthread(RAII 自动合并与支持协作取消的线程)以及原子等待通知机制。

浙公网安备 33010602011771号