using for Enumeration Values
对比一下C++20前后的区别:
enum class State { open, progress, done = 9 }; // Before C++20 void print(State s) { switch (s) { case State::open: std::cout << "openn"; break; case State::done: std::cout << "donen"; break; case State::progress: std::cout << "progressn"; break; default: assert(nullptr); } }
// Since C++20 void print1(State s) { using enum State; switch (s) { case open: std::cout << "openn"; break; case done: std::cout << "donen"; break; case progress: std::cout << "progressn"; break; default: assert(nullptr); } } void print2(State s) { using State::open, State::done, State::progress; switch (s) { case open: std::cout << "openn"; break; case done: std::cout << "donen"; break; case progress: std::cout << "progressn"; break; default: assert(nullptr); } }
Range-Based for Loop with Initialization
基于范围的for循环是C++11引入的新特性,自C++20起,基于范围循环也可以进行初始化。
int main() { std::vector v{1, 2, 3}; for (int i{1}; const auto& item : v) std::cout << std::format("{}: {}n", i++, item); }
Feature Test Macros
特性测试宏,正如其名,是为了当前版本编译器是否支持某个语言特性。这个宏以__cpp为前缀。
#if __cpp_generic_lambdas >= 201707 // generic lambdas with template parameters can be used #endif #ifndef __cpp_lib_as_const template <typename T> const T& as_const(T& t) { return t; } #endif
Attribute [[no_unique_address]]
#include <iostream> struct Empty {}; struct I { int i; }; struct S { Empty e; int i; }; int main() { std::cout << "sizeof(Empty): " << sizeof(Empty) << 'n'; std::cout << "sizeof(I): " << sizeof(I) << 'n'; std::cout << "sizeof(S): " << sizeof(S) << 'n'; }
空类为了区分不同对象的地址,字节大小是1;而结构体S由于内存对齐的原因,所以字节大小是8。输出结果毫无疑问是1,4,8。
#include <iostream> struct Empty {}; // EBCO struct S : Empty { int i; }; // no_unique_address struct S2 { [[no_unique_address]] Empty e; int i; }; int main() { std::cout << "sizeof(Empty): " << sizeof(Empty) << 'n'; std::cout << "sizeof(S): " << sizeof(S) << 'n'; std::cout << "sizeof(S2): " << sizeof(S2) << 'n'; }
注解标签no_unique_address能起到和空基类优化相同的效果。
Attributes [[likely]] and [[unlikely]]
在if/else,switch分支当中都可以使用,帮助编译器作分支预测的优化。
int f(int n) { if (n <= 0) [[unlikely]] { return n; } else { return n * n; } } int g(int n) { if (n <= 0) { return n; } else [[likely]] { return n * n; } } int h(int n) { switch (n) { case 1: // break; [[likely]] case 2: // break; } return 0; }
Attribute [[nodiscard]] with Parameter
nodiscard用于修饰函数,当被修饰的函数发生调用(仅仅调用而不作赋值或者强制转换操作),编译器会报警告信息。
[[nodiscard]] int f(int n) { return n; } int main() { f(1); // Warning int n = f(1); // OK reinterpret_cast<int *>(f(1)); // OK }
New Character Type char8_t
using namespace std::literals; auto c = u8'c'; // char8_t auto s = u8"Hello World"; // const char8_t * auto str1 = u8"Hello World"s; // std::u8string auto str2 = u8"Hello World"sv; // std::u8string_view std::cout << u8'c' << 'n'; // OK in C++17, error in C++20 std::cout << u8"Hello Worldn"; // OK in C++17, error in C++20 std::cout << u8"Hello Worldn"s; // OK in C++17, error in C++20 std::cout << u8"Hello Worldn"sv; // OK in C++17, error in C++20 std::cout << c << 'n'; // OK in C++17, error in C++20 std::cout << s << 'n'; // OK in C++ 17, error in C++20 std::cout << str1 << 'n'; // OK in C++17, error in C++20 std::cout << str2 << 'n'; // OK in C++17, error in C++20
更多的介绍将在下次带来,感谢支持😃