C++ 23 是 C++ 编程语言的最新标准版本,于 2023 年正式发布,带来了诸多新特性与改进,以下是一些主要内容:
1.语言特性
1.显式对象参数(Deducing this):显式对象参数(Deducing this)允许在非静态成员函数中显式指定对象参数。在以往的 C++ 版本中,this指针是隐式传递的,而 C++ 23 提供了一种更明确的方式来处理对象参数,这在一些复杂的编程场景和元编程场景下非常有用。
class MyClass {
public:
void myFunction(MyClass* this, int arg) {
// 函数实现
}
};
在这个例子中,myFunction成员函数显式地指定了对象参数MyClass* this。这种写法使得函数调用的对象关系更加明确。
2.多维下标运算符重载:方便处理多维数组,让多维数组的访问和操作更加直观自然。比如
int arr[2][3][4];
arr[1][2][3] = 42; // 传统方式访问多维数组元素
// C++23 中可以这样重载下标运算符
class MyArray {
public:
int& operator()(int i, int j, int k) {
// 返回对应元素的引用
return data[i][j][k];
}
private:
int data[2][3][4];
};
MyArray myArr;
myArr(1, 2, 3) = 42; // 通过重载的下标运算符访问和修改元素
3.静态运算符函数:引入静态operator(),使得静态成员函数可以像普通运算符一样被调用,增强了代码的灵活性和可读性。
class MathUtils {
public:
static int operator()(int a, int b) {
return a + b;
}
};
int result = MathUtils()(5, 3); // 调用静态 operator() 实现加法运算
4. if consteval和if not consteval:用于在编译时进行条件判断并执行常量评估的语句,可用于优化代码和实现一些编译时的计算逻辑。
consteval int factorial(int n) {
if (n == 0) return 1;
else return n * factorial(n - 1);
}
constexpr int result1 = factorial(5); // 编译时计算阶乘
int runtime_value = 4;
int result2 = 0;
if not consteval {
result2 = factorial(runtime_value); // 运行时计算阶乘
}
5.扩展的浮点类型:新增了std::float{16|32|64|128}_t和std::bfloat16_t等可选的扩展浮点类型,为数值计算提供了更多的精度选择。
std::float32_t myFloat32 = 3.14f;
std::float64_t myFloat64 = 3.14159265358979323846;
std::float128_t myFloat128 = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679;
二、标准库特性
1.<expected>头文件与std::expected类型:用于处理函数可能返回的预期值和错误,将成功和失败的结果封装在单一的返回类型中,增强了错误处理的可读性和可维护性。例如,在文件读取操作中。
#include <expected>
#include <fstream>
#include <iostream>
std::expected<std::string, std::string> readFile(const std::string& filename) {
std::ifstream file(filename);
if (file.is_open()) {
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
file.close();
return content;
} else {
return std::unexpected("Error opening file: " + filename);
}
}
int main() {
auto result = readFile("test.txt");
if (result.has_value()) {
std::cout << "File content: " << result.value() << std::endl;
} else {
std::cerr << "Error: " << result.error() << std::endl;
}
return 0;
}
2.<generator>头文件与std::generator:用于创建同步协程生成器,方便生成一系列的值,简化了异步编程中的数据生成逻辑。
#include <generator>
#include <iostream>
std::generator<int> generateNumbers() {
for (int i = 0; i < 5; ++i) {
co_yield i;
}
}
int main() {
auto gen = generateNumbers();
for (auto num : gen) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
3. 范围库的增强:新增了多个范围适配器和约束范围算法,如views::adjacent、views::adjacent_transform、ranges::starts_with、ranges::ends_with等,使对数据序列的操作更加丰富和灵活.
#include <iostream>
#include <string>
int main() {
std::string str = "Hello, World!";
bool contains_world = str.contains("World");
std::cout << "Contains 'World'? " << (contains_world? "Yes" : "No") << std::endl;
std::string_view str_view = "This is a test";
bool contains_test = str_view.contains("test");
std::cout << "Contains 'test'? " << (contains_test? "Yes" : "No") << std::endl;
return 0;
}
4.新的字符串处理方法:如std::basic_string::contains和std::basic_string_view::contains,方便判断字符串中是否包含特定的子串。
#include <iostream>
#include <string>
int main() {
std::string str = "Hello, World!";
bool contains_world = str.contains("World");
std::cout << "Contains 'World'? " << (contains_world? "Yes" : "No") << std::endl;
std::string_view str_view = "This is a test";
bool contains_test = str_view.contains("test");
std::cout << "Contains 'test'? " << (contains_test? "Yes" : "No") << std::endl;
return 0;
}
三、其他方面
1.模块系统的改进:进一步优化了模块的加载和编译性能,新的模块导入语法使模块间依赖关系更明确,降低了耦合度,有助于提高大型项目的开发效率和代码的可维护性,例如在游戏开发项目中可更好地划分和封装不同功能模块.
2.增强的概念(Concepts):对概念的语法进行了简化和改进,使概念定义更清晰易懂,能更精确地约束模板参数,避免类型不匹配错误,在模板元编程中的应用也得到增强,提高了代码的灵活性和可复用性.
3.预处理指令的扩展:新增了#elifdef、#elifndef、#warning等预处理指令,提高了条件编译的清晰度和灵活性.
#ifdef _WIN32
// 包含Windows平台相关的头文件
#include <windows.h>
#elifdef __APPLE__
// 包含苹果平台相关的头文件
#include <CoreFoundation/CoreFoundation.h>
#elifdef __linux__
// 包含Linux平台相关的头文件
#include <stdio.h>
#endif
4.UTF-8 源文件编码:规定 UTF-8 为可移植的源文件编码,确保不同平台上字符表示的一致性.
#include <iostream>
#include <string>
void setMenuItemTitle(std::string title) {
std::cout << "设置菜单标题为: " << title << std::endl;
}
int main() {
std::string frenchTitle = "Ouvrir";// 法语:打开
std::string germanTitle = "Öffnen";// 德语:打开
std::string chineseTitle = "打开";
setMenuItemTitle(frenchTitle);
setMenuItemTitle(germanTitle);
setMenuItemTitle(chineseTitle);
return 0;
}
在这个例子中,无论是法语、德语还是中文的字符串,都可以在 UTF - 8 编码的源文件中正确地表示和处理。这使得程序能够更好地适应全球化的需求,并且在不同的操作系统和终端设备上,只要它们正确地支持 UTF - 8 编码,就能够正确地显示这些文本信息。