概述常用C++20技术点
一、Importing Modules 导入模块
c++ 20的一个较大的新特性是对模块的支持,它取代了所谓头文件的旧机制
import <iostream>; //C++20 导入模块
#include <iostream> //传统包含头文件的方式
VS2022 支持导入模块的设置
- 属性-》属性配置-》常规-》C++语言标准-》预览最新(/std::C++latest)
- 属性-》属性配置-》C/C+±》常规-》扫描以查找依赖关系-》是
- 属性-》属性配置-》C/C+±》语言-》启用实验性的C++标准库模块
二、推荐使用 format 格式化输出
import <format>;
std::cout << std::format("hello world {}",100) << std::endl;
int uninitializedInt;
int initializedInt{ 7 }; //统一的变量初始化
cout << format("{} is a random value", uninitializedInt) << endl;
cout << format("{} was assigned an initial value", initializedInt) << endl;
三、Numerical Limits 数值范围
cout << "int:\n";
cout << format("Max int value: {}\n", numeric_limits<int>::max());
cout << format("Min int value: {}\n", numeric_limits<int>::min());
cout << format("Lowest int value: {}\n", numeric_limits<int>::lowest());
cout << "\ndouble:\n";
cout << format("Max double value: {}\n", numeric_limits<double>::max());
cout << format("Min double value: {}\n", numeric_limits<double>::min());
cout << format("Lowest double value: {}\n", numeric_limits<double>::lowest());
四、casting 强制类型转换
float myFloat { 3.14f };
int i1 { (int)myFloat }; // method 1 C语言方式 不推荐
int i2 { int(myFloat) }; // method 2 不推荐
int i3 { static_cast<int>(myFloat) }; // method 3 推荐使用
五、Enumerated Types 枚举类型
旧式枚举不是强类型的,这意味着它们不是类型安全的。它们总是被解释为整数,可能无意中比较来自完全不同枚举类型的枚举值,或者将错误枚举类型的枚举值传递给函数。
//老式 没有范围限定
enum PieceTypeOld { PieceTypeKing, PieceTypeQueen, PieceTypeRook, PieceTypePawn };
PieceTypeOld old = PieceTypeKing;
//C++20 有范围限定 安全
enum class PieceTypeNew
{
King = 1,
Queen,
Rook = 10,
Pawn
};
using PieceTypeNew::King;
PieceTypeNew piece1{ King };
PieceTypeNew piece2{ PieceTypeNew::Queen };
六、自定义模块
//文件名也可以.cppm 后缀
export module Employee;
export struct Employee
{
char firstInitial;
char lastInitial;
int employeeNumber;
int salary;
};
import <iostream>; //导入模块
import <format>;
//导入自定义模块不需要尖括号
import Employee;
using namespace std;
int main()
{
//自定义导出模块
Employee anEmployee;
anEmployee.firstInitial = 'J';
anEmployee.lastInitial = 'D';
anEmployee.employeeNumber = 42;
anEmployee.salary = 80000;
// Output the values of an employee.
cout << format("Employee: {}{}", anEmployee.firstInitial,
anEmployee.lastInitial) << endl;
cout << format("Number: {}", anEmployee.employeeNumber) << endl;
cout << format("Salary: ${}", anEmployee.salary) << endl;
}
七、if/switch
/**********************************************************/
//传统if语句
if (i > 4)
{
// Do something.
} else if (i > 2)
{
// Do something else.
} else
{
// Do something else.
}
//if语句的初始化列表形式
if (<initializer>; <conditional_expression>)
{
<if_body>
} else if (<else_if_expression>) {
<else_if_body>
} else
{
<else_body>
}
if (Employee employee { getEmployee() }; employee.salary > 1000)
{
}
/***************************************************************/
//传统switch语句
switch (menuItem)
{
case OpenMenuItem:
// Code to open a file
break;
case SaveMenuItem:
// Code to save a file
break;
default:
// Code to give an error message
break;
}
//C++20
switch (<initializer>; <expression>)
{
<body>
}
八、Three-Way Comparisons 三元操作符 <=>
/*******************************三元操作符*********************************/
// <=> 又被叫做宇宙飞船操作符(形状像是宇宙飞船)
//strong_ordering::less: First operand less than second
//strong_ordering::greater : First operand greater than second
//strong_ordering::equal : Equal operands
int i{ 11 };
strong_ordering result{ i <=> 0 };
if (result == strong_ordering::less) { cout << "less" << endl; }
if (result == strong_ordering::greater) { cout << "greater" << endl; }
if (result == strong_ordering::equal) { cout << "equal" << endl; }
if (is_lt(result)) { cout << "less" << endl; }
if (is_gt(result)) { cout << "greater" << endl; }
if (is_eq(result)) { cout << "equal" << endl; }
九、Attributes 属性
1. [[nodiscard]]
告诉编译器 这个函数返回值必须被使用,否则编译发出警告 warning C4834: 放弃具有 “nodiscard” 属性的函数的返回值
此属性通常用来修饰返回错误码的函数(警告这个返回值不能忽视)
import <iostream>; //导入模块
using namespace std;
//[[nodiscard]] 属性告诉编译器 这个函数返回值必须被使用,否则编译发出警告 warning C4834: 放弃具有 "nodiscard" 属性的函数的返回值
[[nodiscard]] int func()
{
return 42;
}
//C++20之后可以自定义警告消息
[[nodiscard("这个返回值不能忽视")]] int func2()
{
return 42;
}
int main()
{
func();
func2();
}
2. [[maybe_unused]]
告诉编译器在某些东西未使用时不用发出警告
import <iostream>; //导入模块
using namespace std;
int func2(int param1,[[maybe_unused]]int param2)
{
return 42;
}
int main()
{
func2();
}
3. [[noreturn]]
告诉编译器不会将控制权返回到调用站点
import <iostream>; //导入模块
import <format>;
using namespace std;
//如果不加 [[noreturn]] 发出警告 warning C4715: “isFeatureLicensed”: 不是所有的控件路径都返回值
[[noreturn]] void forceProgramTermination()
{
std::exit(1);
}
bool isDongleAvailable()
{
bool isAvailable{ false };
return isAvailable;
}
bool isFeatureLicensed(int featureId)
{
if (!isDongleAvailable()) {
forceProgramTermination();
}
else {
bool isLicensed{ featureId == 42 };
return isLicensed;
}
}
int main()
{
//[[noreturn]]
bool bLicense{ isFeatureLicensed(42) };
}
4. [[deprecated]]
可以用来标记某些东西已被弃用,这意味着您仍然可以使用它,但不鼓励使用它,参数可以指定弃用原因
[[deprecated("Unsafe method, please use xyz")]] void func();
5. [[likely]] [[unlikely]]
帮助编译器优化代码,多用于if switch 分支中
int value { /* ... */ };
if (value > 11) [[unlikely]]
{
/* Do something ... */
}
else
{
/* Do something else... */
}
switch (value)
{
[[likely]] case 1:
// Do something ...
break;
case 2:
// Do something...
break;
[[unlikely]] case 12:
// Do something...
break;
}