
C++14 的定位
C++14(ISO/IEC 14882:2014)没有引入新概念,它把 C++11 里”能用但不顺手”的能力放开:函数返回类型推导、泛型 lambda、constexpr 循环。属于完善型升级,从 11 迁移成本极低。

函数返回类型推导
// C++11:必须写尾置返回类型
auto add11(int a, int b) -> int { return a + b; }
// C++14:直接推导
auto add14(int a, int b) { return a + b; }
// decltype(auto):保留引用性
int x = 0;
decltype(auto) r = (x); // int&,推导结果带引用
模板函数里最有用:decltype(auto) 把模板参数的引用性原样带出。注意别让推导结果带着局部变量的引用返回——那是悬垂引用。
泛型 Lambda 与初始化捕获
// C++11:lambda 参数类型必须写明
auto lambda11 = [](int x, int y) { return x + y; };
// C++14:参数用 auto,等价于一个模板 lambda
auto lambda14 = [](auto x, auto y) { return x + y; };
int i = lambda14(3, 4); // int 实例
double d = lambda14(3.5, 4.5); // double 实例
// 初始化捕获:捕获的是"表达式的值"而不是变量
int factor = 10;
auto f = [mul = factor * 2](int x) { return x * mul; }; // 捕获 20
初始化捕获还能捕获只可移动的对象(unique_ptr、文件句柄):[p = std::move(ptr)],C++11 里做不到。
constexpr 增强
// C++11:函数体只能一条 return,基本不可用
constexpr int sq11(int x) { return x * x; }
// C++14:允许局部变量、循环、if 分支
constexpr int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; ++i)
result *= i;
return result;
}
static_assert(factorial(5) == 120, ""); // 编译期算出 120
这之后编译期计算才真正落地:配置表、哈希、查表算法都能在编译期算好,运行时零开销。
变量模板
template <typename T>
constexpr T pi = T(3.14159265358979323846);
double r = 2 * pi<double>; // 按类型实例化
float s = pi<float>;
常量按类型取不同精度,标准库的 std::is_integral_v<T> 这类 _v 后缀变量模板就是它的产物。
字面量增强
int a = 0b1010; // 二进制字面量:10
int b = 1'000'000; // 数字分隔符:一百万,大数可读性
int c = 0xFF'FF; // 位掩码按字节分组
其他实用特性
[[deprecated]] 属性
[[deprecated("用 new_func 替代")]]
void old_func();
old_func(); // 编译告警,提示替代方案
std::make_unique
C++11 有 make_shared 却没有 make_unique,14 补上。统一用 make_* 工厂:省一次显式 new,异常安全(参数求值顺序不会泄漏)。
std::exchange
// 读旧值 + 写新值合成一步,写移动赋值运算符时常用
old = std::exchange(ptr, nullptr); // old 拿到旧值,ptr 被置空
读写锁 shared_timed_mutex
多读单写场景:读用 shared_lock 并发进入,写用 unique_lock 独占。
std::cbegin / std::cend
显式获取只读迭代器,模板泛型代码里避免 const 推导问题。
实战体会
C++14 是迁移性价比最高的一次升级:没有破坏性改动,却能删掉大量样板代码。泛型 lambda 让我把散落各处的函数对象清理掉了大半;constexpr 增强则让”配置即代码”真正可行——编译期算好的表运行时直接查,连初始化检查都由编译器代劳。



