C++17 是 C++ 标准中的一个重要版本,带来了许多新的语言特性和标准库的增强。以下是 C++17 的一些主要新特性以及它们的用途和示例。
1. if constexpr (编译期分支)
if constexpr 允许在编译期根据条件选择不同的代码路径,可以用于编译时类型检测和模板元编程,避免编译期错误。
#include <iostream>template <typename T>
void print_type_info(const T& value) {if constexpr (std::is_integral_v<T>) {
std::cout << "Integer: " << value << '\n';
} else if constexpr (std::is_floating_point_v<T>) {
std::cout << "Floating point: " << value << '\n';
} else {
std::cout << "Other type: " << value << '\n';
}
}
int main() {print_type_info(42); // 输出: Integer: 42print_type_info(3.14); // 输出: Floating point: 3.14print_type_info("Hello"); // 输出: Other type: Hello
}
2. 结构化绑定(Structured Bindings)
结构化绑定允许解包结构体、数组、元组等,并将其成员直接绑定到变量上,使代码更加简洁。
#include <tuple>
#include <iostream>
std::tuple<int, double, std::string> getData() {return {1, 2.3, "example"};
}
int main() {auto [i, d, s] = getData(); // 解包 tuple
std::cout << i << ", " << d << ", " << s << '\n';
}
3. 折叠表达式(Fold Expressions)
折叠表达式简化了可变参数模板中的参数展开操作,允许对参数包进行自动的运算折叠。
#include <iostream>template <typename... Args>
auto sum(Args... args) {return (args + ...); // 右折叠
}
int main() {
std::cout << sum(1, 2, 3, 4) << '\n'; // 输出: 10
}
4. std::optional(可选类型)
std::optional 是一种可以包含或不包含值的类型,用于替代需要明确返回 nullptr 或类似语义的场景。
#include <iostream>
#include <optional>
std::optional<int> find(bool found) {if (found)return 42;elsereturn std::nullopt;
}
int main() {auto result = find(true);if (result) {
std::cout << "Found: " << *result << '\n';
} else {
std::cout << "Not found\n";
}
}
5. std::variant(代替 union)
std::variant 是一个类型安全的 union,允许不同类型的值存储在同一个对象中。
#include <iostream>
#include <variant>
int main() {
std::variant<int, float, std::string> data;
data = 10; // 可以存储整数
data = "Hello"; // 可以存储字符串
std::visit([](auto&& arg) {
std::cout << arg << '\n'; // 访问并打印存储的值
}, data);
}
6. std::string_view(字符串视图)
std::string_view 提供了一种轻量级的、不拥有数据的字符串类,它允许更高效的字符串操作。
#include <iostream>
#include <string_view>
void print(std::string_view sv) {
std::cout << sv << '\n';
}
int main() {
std::string str = "Hello, World!";print(str); // 传递 std::stringprint("Hello again"); // 传递字符串字面量
}
7. 内联变量(Inline Variables)
C++17 允许变量使用 inline 修饰符,支持在头文件中定义全局变量,而不会导致链接错误。
// header.hinline int global_var = 10;
// main.cpp#include "header.h"#include <iostream>int main() {
std::cout << global_var << '\n'; // 输出: 10
}
8. std::filesystem(文件系统库)
C++17 增加了标准文件系统库,提供了文件操作、目录遍历等功能。
#include <iostream>
#include <filesystem>
int main() {
std::filesystem::path path = "/tmp/test.txt";
if (std::filesystem::exists(path)) {
std::cout << "File exists: " << path << '\n';
} else {
std::cout << "File does not exist\n";
}
}
9. 模板参数推导(Class Template Argument Deduction)
C++17 支持类模板的自动参数推导,类似于函数模板的参数推导。
#include <array>
#include <iostream>
int main() {
std::array arr = {1, 2, 3}; // 自动推导类型为 std::array<int, 3>for (int i : arr) {
std::cout << i << '\n';
}
}
10. std::any(任意类型存储)
std::any 提供了一种能够存储任意类型对象的容器,且无需提前指定类型。
#include <iostream>
#include <any>int main() {
std::any data = 10;
std::cout << std::any_cast<int(data) << '\n';
data = std::string("Hello");
std::cout << std::any_cast<std::string>(data) << '\n';
}
11. [[nodiscard]] 属性
[[nodiscard]] 属性用于标记一个函数的返回值不能被忽略,如果忽略会产生编译警告。
[[nodiscard]] int calculate() {return 42;
}
int main() {calculate(); // 编译器可能会发出警告,提醒返回值没有被使用
}
12. Lambda 表达式的新特性
C++17 允许 lambda 表达式捕获 *this,以及引入了 lambda 的 constexpr 支持。
#include <iostream>
class MyClass {
public:int value = 10;
auto create_lambda() const {return [*this]() { // 捕获当前对象的副本
std::cout << value << '\n';
};
}
};
int main() {
MyClass obj;auto lambda = obj.create_lambda();lambda(); // 输出: 10
}
13. Tuple,函数返回多值
C++17 允许使用Tuple 从函数返回多值,使用tie接受返回值
#include <iostream>
using namespace std;
tuple<int ,string,string> stu(){
return {7,"bbs","kk"}
}
int main(){
int age;
string name;
string school;
tie(age,name,school)=stu();
cout<<age<<name <<school;
}
总结
C++17 引入了许多有用的新特性,包括编译期优化、模板编程增强、以及新的标准库功能。这些特性让代码更简洁、更高效,也使得编写安全、可维护的代码变得更容易。