對比一下C++20前後的區別:
enum class State {
open,
progress,
done = 9
};
// Before C++20
void print(State s) {
switch (s) {
case State::open:
std::cout << "open\n";
break;
case State::done:
std::cout << "done\n";
break;
case State::progress:
std::cout << "progress\n";
break;
default:
assert(nullptr);
}
}
// Since C++20
void print1(State s) {
using enum State;
switch (s) {
case open:
std::cout << "open\n";
break;
case done:
std::cout << "done\n";
break;
case progress:
std::cout << "progress\n";
break;
default:
assert(nullptr);
}
}
void print2(State s) {
using State::open, State::done, State::progress;
switch (s) {
case open:
std::cout << "open\n";
break;
case done:
std::cout << "done\n";
break;
case progress:
std::cout << "progress\n";
break;
default:
assert(nullptr);
}
}
基於範圍的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);
}
特性測試宏,正如其名,是為了當前版本編譯器是否支援某個語言特性。這個宏以__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
#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能起到和空基礎類別優化相同的效果。
在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;
}
nodiscard用於修飾函數,當被修飾的函數發生呼叫(僅僅呼叫而不作賦值或者強制轉換操作),編譯器會報警告資訊。
[[nodiscard]]
int f(int n) {
return n;
}
int main() {
f(1); // Warning
int n = f(1); // OK
reinterpret_cast<int *>(f(1)); // OK
}
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 World\n"; // OK in C++17, error in C++20
std::cout << u8"Hello World\n"s; // OK in C++17, error in C++20
std::cout << u8"Hello World\n"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
更多的介紹將在下次帶來,感謝支援