跳到主要内容

C++ 14概述

引言

C++14是C++11之后的第一个小幅度更新版本,于2014年正式发布。虽然C++14相比C++11的变化不那么剧烈,但它通过修复漏洞、完善功能和添加一些新特性,使C++编程语言更加强大和易用。C++14主要聚焦于改善C++11中已经引入的特性,并进一步提升了开发者体验。

对于初学者来说,了解C++14的新特性不仅能让你写出更简洁、更现代的代码,还能帮助你更好地理解C++语言的发展方向。

备注

虽然称为"小幅度更新",但C++14中引入的特性对提升代码质量和开发效率仍然有很大帮助。

C++ 14的主要新特性

1. 函数返回类型推导

在C++11中,我们可以使用auto关键字来推导变量的类型,但函数的返回类型仍然需要显式声明。C++14允许编译器自动推导函数的返回类型,使代码更加简洁。

cpp
// C++11
auto add(int a, int b) -> int {
return a + b;
}

// C++14
auto add(int a, int b) {
return a + b;
}

这一特性在使用模板或处理复杂返回类型时尤为有用:

cpp
auto createPair() {
return std::make_pair(1, "Hello"); // 返回类型为std::pair<int, const char*>
}

2. 变量模板

C++14引入了变量模板,允许我们定义依赖于类型的常量:

cpp
template<typename T>
constexpr T pi = T(3.1415926535897932385);

// 使用
float radius = 2.0f;
float circumference = 2 * pi<float> * radius;

double precise_radius = 2.0;
double precise_circumference = 2 * pi<double> * precise_radius;

3. 泛型lambda表达式

C++11引入了lambda表达式,而C++14进一步扩展,允许在lambda参数列表中使用auto关键字,创建泛型lambda:

cpp
// C++14泛型lambda
auto multiply = [](auto a, auto b) {
return a * b;
};

// 使用
int result1 = multiply(5, 3); // 结果为15
double result2 = multiply(2.5, 3.0); // 结果为7.5

这样写出的lambda可以处理不同类型的参数,类似于函数模板。

4. Lambda捕获初始化

C++14允许在lambda捕获列表中使用表达式初始化新变量:

cpp
int x = 4;
auto y = [z = x + 1]() {
return z * 2;
}(); // y = (4 + 1) * 2 = 10

这在需要捕获转换后的值或表达式结果时非常有用。

5. 改进的constexpr

C++14大幅放宽了constexpr函数的限制,允许它们包含:

  • 多条语句
  • 局部变量声明
  • 循环和条件语句
  • 以及其他在C++11中被禁止的结构
cpp
// C++14中的constexpr函数
constexpr int factorial(int n) {
int result = 1;
for(int i = 1; i <= n; ++i) {
result *= i;
}
return result;
}

// 编译时计算
constexpr int fact5 = factorial(5); // 120,在编译时计算

6. 二进制字面量

C++14引入了二进制字面量,允许使用0b0B前缀来表示二进制数:

cpp
int binary = 0b1010;  // 十进制中的10
int mask = 0B1100'1010; // 单引号可作为数字分隔符,提高可读性

7. 数字分隔符

如上例所示,C++14允许在数字字面量中使用单引号作为分隔符,提高可读性:

cpp
long long population = 7'600'000'000;
double avogadro = 6.022'140'76e23;

8. std::make_unique

C++11引入了智能指针std::shared_ptr和相应的std::make_shared工厂函数,但遗漏了std::unique_ptr的工厂函数。C++14修复了这一漏洞,添加了std::make_unique

cpp
// C++11/14都可用的写法
std::unique_ptr<int> p1(new int(42));

// 仅C++14可用的更安全写法
auto p2 = std::make_unique<int>(42);

使用std::make_unique的好处包括:

  • 更简洁的语法
  • 异常安全
  • std::make_shared保持一致性

实际应用场景

场景1: 简化数据处理代码

cpp
// 处理不同类型的数据集合
std::vector<int> nums = {1, 2, 3, 4, 5};
std::vector<std::string> words = {"hello", "world"};

auto processCollection = [](const auto& collection) {
for(const auto& item : collection) {
std::cout << item << " ";
}
std::cout << std::endl;
};

processCollection(nums); // 输出: 1 2 3 4 5
processCollection(words); // 输出: hello world

场景2: 构建更灵活的数据结构

cpp
class DataManager {
private:
template<typename T>
struct DataHolder {
T data;
std::string metadata;
};

// 使用C++14的变量模板存储每种类型的默认值
template<typename T>
static constexpr T default_value = T{};

// 特化某些类型的默认值
static constexpr int default_value<int> = -1;
static constexpr double default_value<double> = 0.0;

public:
template<typename T>
auto createDataItem(const std::string& meta = "") {
return std::make_unique<DataHolder<T>>(
DataHolder<T>{default_value<T>, meta}
);
}
};

场景3: 编译时计算和优化

cpp
// 使用改进的constexpr计算斐波那契数列
constexpr int fibonacci(int n) {
if (n <= 1) return n;

int a = 0, b = 1;
for (int i = 2; i <= n; ++i) {
int tmp = a + b;
a = b;
b = tmp;
}
return b;
}

// 编译时计算第10个斐波那契数
constexpr int fib10 = fibonacci(10); // 55

// 运行时计算
int userInput = 8;
int result = fibonacci(userInput); // 21

C++ 14对性能的影响

C++14的改进不仅提升了代码的可读性和编写效率,还在某些方面改善了运行时性能:

  1. 编译时计算: 增强的constexpr允许更多的计算在编译时完成,减少运行时开销
  2. 优化机会: 更清晰的代码意图(如使用auto返回类型)可能为编译器提供更多优化机会
  3. 智能指针改进: std::make_unique等工具函数提高了内存管理效率和安全性
提示

现代C++编译器对C++14特性的支持已经非常完善,使用这些特性通常不会引入额外的运行时开销。

总结

C++14虽然是相对较小的一次更新,但它通过以下方式显著提升了C++编程体验:

  1. 简化语法: 函数返回类型推导、数字分隔符等特性使代码更简洁
  2. 增强泛型编程: 泛型lambda、变量模板等特性扩展了模板编程的能力
  3. 改进编译时编程: 增强的constexpr使更多计算能在编译期完成
  4. 完善标准库: 添加了缺失的工具如std::make_unique
  5. 提高代码质量: 新特性鼓励更现代、更安全的编程实践

掌握C++14特性使你能够写出更简洁、更安全、性能更好的代码。对于追求现代C++编程风格的开发者来说,C++14是必须熟悉的标准。

学习资源与练习

练习1: 泛型lambda与auto返回类型

尝试编写一个泛型lambda表达式,接受任意类型的容器,返回其中元素的总和:

cpp
// 提示:
auto sum = [](const auto& container) {
// 使用容器元素类型的默认值初始化result
// 遍历容器并累加元素
// 返回结果
};

练习2: 使用make_unique和改进的constexpr

实现一个工厂函数,创建不同几何形状对象,并使用constexpr计算它们的一些属性:

cpp
// 提示:
class Shape {
public:
virtual double area() const = 0;
virtual ~Shape() = default;
};

class Circle : public Shape {
// 实现
};

class Rectangle : public Shape {
// 实现
};

// 使用make_unique创建形状
auto createShape(const std::string& type, double... params) {
// 实现
}

// 使用constexpr计算一些几何常量
constexpr double calculatePi() {
// 使用级数展开或其他方法近似计算π值
}

推荐学习资源

  1. cppreference.com C++14页面 - 完整的C++14特性参考
  2. 《Effective Modern C++》by Scott Meyers - 深入解释C++11/14的最佳实践
  3. C++ Core Guidelines - 包含使用C++14特性的建议和指南

C++14的特性为编写现代C++代码奠定了基础,并为后续的C++17和C++20标准铺平了道路。通过实践这些特性,你可以更好地理解C++语言的进化方向。