在C++语言的发展过程中,C++11、C++14和C++17标准为程序员带来了许多令人兴奋的新特性。这些新特性不仅简化了编程,还提高了代码的质量和可读性。本文将深入探讨这些新特性,并提供一些示例代码,帮助读者更好地理解和应用这些特性。
假设读者已经具备了完整的C++11知识基础。这不是一篇面向初学者的文章。
C++14引入了二进制字面量,使得表示二进制数更加直观。同时,auto关键字的使用也得到了扩展,可以自动推断变量类型。
int a = 0b111; // a = 7
auto str = "hello"s; // auto deduces string
auto dur = 60s; // auto deduces chrono::seconds
auto z = 1i; // auto deduces complex
C++14还引入了数字分隔符,使得阅读大数字(尤其是64位指针)变得更加容易。
int a = 1'000'000;
C++14允许使用变量模板,这使得可以为不同类型的变量提供相同的名称。
template <typename T>
T pi = (T)3.141592;
double x = sin(2.0 * 440.0 * pi<double> * 0.01);
float perimeter = 2.0f * pi<float> * radius;
C++14允许在函数声明时使用auto关键字,编译器将自动推导返回类型。
auto foo(int j, int x) {
return j + x; // "auto" -> "int";
}
auto tu() {
return make_tuple<int, int, int>(5, 6, 7);
}
C++14允许在Lambda表达式中使用auto关键字,简化了类型声明。
auto lambda = [](auto x, auto y) {
return x + y;
};
C++17进一步简化了命名空间的使用,可以直接使用嵌套命名空间。
namespace A::B::C {
// ...
}
C++17引入了结构化绑定,使得可以更简单地解包tuple或pair。
tuple<int, float, char> x() {
return make_tuple<int, float, char>(5, 5.2f, 'c');
}
auto [a, b, c] = x();
C++17引入了std::optional,允许返回一个“无值”的状态,并提供了一个catchall案例。
optional<string> foo() {
if (something)
return "Hello";
return {};
}
C++17引入了std::any,它是一个可以存储任何类型的容器。
any foo() {
string h("hello");
return any(h);
}
C++17引入了std::variant,它是一个类型安全的联合体。
variant<int, float, char> x;
x = 5; // now contains int
int i = std::get<int>(v); // i = 5;
C++17引入了折叠表达式,它允许以更简洁的方式编写模板代码。
template <typename T, typename ... Many>
T add(T t, Many... many) {
return (t + ... + many);
}
C++17引入了__has_include预处理器,它允许在编译时检查某个头文件是否可用。
#if __has_include(<string>)
// Assume <string> has been included
#endif
C++17允许在模板参数中使用auto关键字,从而简化了模板的使用。
template <auto value>
void foo() { }
foo<3>();
C++14和C++17引入了许多新的属性,如[[deprecated]]、[[fallthrough]]、[[nodiscard]]和[[maybe_unused]],这些属性帮助更好地控制代码的行为。
[[deprecated("This function is not safe")]] void foo() { }
switch (a) {
case 1:
test();
// Warning issued, did the programmer forget the break statement?
case 2:
test2();
[[fallthrough]];
// No warning, the lack of break was intentional
case 3:
// ...
}
C++17允许在if和switch语句中初始化变量,这些变量的作用域仅限于if或switch语句内部。
if (int val = foo(); val == 1) {
// ...
}
C++17允许在头文件中定义内联变量,这些变量可以被多次包含,而不会重复定义。
inline int x = 5;
C++17允许使用auto关键字从初始化列表中自动推导类型。
auto x1 = {1, 2};
C++17允许在构造函数模板中使用auto关键字,从而简化了类型推导。
auto p = std::pair(5.0, 0);
C++17将异常规格作为函数指针类型的一部分,这使得异常规格更加严格。
void (*p)() throw(int);
void (**pp)() throw() = &p
C++17引入了string_view,它提供了std::string的所有好处,但不需要动态内存分配。
string a = "hello there";
string_view largeStringView{a.c_str(), a.size()};