C++简介
文章目录
- C++简介
- C++版本
- C++11
- 例子
- C++14
- 例子
- C++17
- C++20
- 例子
C++简介
C++是一种高级编程语言,它是对C语言的扩展和增强。C++由Bjarne Stroustrup于1980年发明,主要用于系统级编程、游戏开发、嵌入式系统等领域。
C++具有许多特性,其中最重要的是面向对象编程(OOP)。面向对象编程使得软件开发更加模块化、可重用和易于理解。C++还支持其他编程范式,如泛型编程、函数式编程等。
C++具有以下特点:
-
高效性:C++编译生成的机器码效率高,可以直接与硬件进行交互,可以在性能要求较高的应用中使用。
-
跨平台性:C++代码可以在不同的操作系统上进行编译和运行,例如Windows、Linux和Mac OS等。
-
强大的标准库:C++标准库提供了丰富的功能,涵盖了各种数据结构、算法、输入输出等。
-
内存管理:C++提供了手动内存管理的能力,程序员可以自己管理内存分配和释放,但也容易导致内存泄漏和悬挂指针等问题。
-
多范式支持:除了面向对象编程外,C++还支持泛型编程(通过模板实现)和函数式编程(通过Lambda表达式和函数对象实现)。
C++广泛应用于各种领域,特别是需要高性能和可控制性的应用,如游戏开发、图形界面开发、嵌入式系统、金融系统、科学计算等。同时,C++也是其他一些流行编程语言的基础,如Java、Python等,很多开源项目也是用C++开发的。
C++版本
C++有多个版本,每个版本都引入了一些新的功能和改进。以下是一些常见的C++版本:
-
C++98/C++03:这是最早的C++标准版本,也被称为C++98或C++03。它包含了基本的面向对象编程特性,如类、继承、多态等,以及一些库,如STL(标准模板库)。
-
C++11:于2011年发布的C++标准,引入了许多新特性,如自动类型推导(auto关键字)、Lambda表达式、右值引用、智能指针、范围for循环等。此外,C++11还增加了一些标准库组件,如std::thread(多线程支持)、std::regex(正则表达式支持)等。
-
C++14:在C++11的基础上进行了一些小的改进和修复,于2014年发布。C++14没有引入太多的新特性,主要是对语法进行了改进和简化。
-
C++17:在2017年发布的C++标准,引入了一些重要的新特性,如结构化绑定、if constexpr、折叠表达式、并行算法等。C++17对并发编程、文件系统操作和元编程等方面进行了改进。
-
C++20:于2020年发布的C++标准,包含了许多新特性,如概念(Concepts)、三向比较运算符、协程(Coroutines)、范围概论(Ranges)、异步操作等。C++20进一步改进了语言的表达能力和库的功能。
请注意,以上只是列举了一些常见的C++版本,随着时间的推移,C++标准会继续演变和更新,引入更多的功能和改进。开发人员可以根据需要选择适合自己项目的C++版本。
C++11
当然,以下是对C++11引入的主要新特性的进一步详细介绍:
-
自动类型推导(auto):使用auto关键字声明变量时,编译器会根据右侧的初始化表达式推导出变量的类型。这样可以简化代码,并且在使用模板时特别有用,可以避免手动指定模板参数类型。
-
Lambda表达式:Lambda表达式允许我们在需要一个函数对象的地方定义一个匿名函数。它的语法形式为
[]() { /* 函数体 */ }
,其中[]是捕获列表,()是参数列表,{}是函数体。Lambda表达式可以方便地在现场创建函数对象,并且可以捕获外部变量,使得代码更加简洁和灵活。 -
右值引用(Rvalue references):右值引用允许我们将右值(临时对象、表达式结果等)绑定到一个可修改的引用上。通过移动语义,我们可以在不进行深拷贝的情况下转移对象的资源,提高性能。另外,右值引用还开启了完美转发的可能性,可以实现更灵活的函数参数传递。
-
智能指针(Smart Pointers):智能指针是C++11引入的三种指针类,包括std::shared_ptr、std::unique_ptr和std::weak_ptr。它们提供了自动内存管理,可以在对象不再需要时自动释放内存,避免了手动调用delete操作和内存泄漏的风险。其中,std::shared_ptr使用引用计数来管理对象的生命周期,std::unique_ptr拥有对象的独占权,而std::weak_ptr则用于解决循环引用问题。
-
范围for循环(Range-based for loop):范围for循环是一种更加简洁的遍历容器元素的语法形式。它使用范围表达式来遍历容器中的每个元素,而无需使用迭代器或者手动控制循环变量。
-
静态断言(static_assert):静态断言是在编译时检查某个条件是否为真的机制。如果条件不满足,则会导致编译错误,并显示用户指定的错误消息。
-
空指针常量(nullptr):C++11引入了一个新的空指针常量nullptr,用于表示空指针,取代了之前使用的NULL宏。nullptr具有明确的类型,并且支持与其他指针类型进行比较。
-
并发编程支持:C++11引入了一些基本的并发编程支持,如std::thread和std::mutex等。这些标准库组件使得多线程编程更加方便和安全,可以轻松创建线程、实现互斥保护和同步操作。
-
泛型编程增强:C++11引入了一些增强的泛型编程特性,包括模板别名(template alias)、可变参数模板(variadic templates)、类型转发(perfect forwarding)等。这些特性使得泛型代码更加灵活和易用,可以更好地支持模板元编程和泛型库开发。
-
移动语义(Move semantics):移动语义是通过移动构造函数和移动赋值运算符来实现的,在对象移动时转移资源的所有权而不是进行深拷贝。移动语义提高了代码的性能和效率,特别适用于处理大规模数据结构和动态内存管理。
除了以上列举的特性,C++11还引入了其他一些新功能和改进,如std::tuple(元组)、std::chrono(时间处理)、委托构造函数(delegating constructors)、标准线程库(std::thread)和正则表达式支持(std::regex)等。这些新特性使得C++11成为一个现代化、更强大的编程语言,提供了更多的工具和选项,以满足开发者的需求。
例子
以下是对C++11引入的一些新特性的简单示例:
-
自动类型推导(auto):
auto num = 10; // 推导出num的类型为int auto name = "John"; // 推导出name的类型为const char*
-
Lambda表达式:
// 使用Lambda表达式求两个数的和 auto sum = [](int a, int b) { return a + b; }; int result = sum(5, 3); // 结果为8
-
右值引用(Rvalue references):
std::string&& rvalueRef = std::move(std::string("Hello")); // 将临时对象绑定到右值引用上
-
智能指针(Smart Pointers):
// 使用std::shared_ptr创建共享所有权的指针 std::shared_ptr<int> sharedPtr(new int(5)); // 使用std::unique_ptr创建独占所有权的指针 std::unique_ptr<int> uniquePtr(new int(10)); // 使用std::weak_ptr创建弱引用,防止循环引用 std::weak_ptr<int> weakPtr = sharedPtr;
-
范围for循环(Range-based for loop):
std::vector<int> numbers = {1, 2, 3, 4, 5}; for (int num : numbers) {std::cout << num << " "; } // 输出结果: 1 2 3 4 5
-
静态断言(static_assert):
static_assert(sizeof(int) == 4, "int类型大小不为4字节"); // 如果条件不满足,编译错误,并输出错误消息
-
空指针常量(nullptr):
int* ptr = nullptr; // 声明一个空指针
-
并发编程支持:
#include <iostream> #include <thread>// 线程函数,打印线程ID void printThreadId() {std::cout << "Thread ID: " << std::this_thread::get_id() << std::endl; }int main() {std::thread thread1(printThreadId); // 创建线程1std::thread thread2(printThreadId); // 创建线程2thread1.join(); // 等待线程1结束thread2.join(); // 等待线程2结束return 0; }
-
移动语义(Move semantics):
class MyString { public:MyString(std::string&& str) : data(std::move(str)) {} // 移动构造函数private:std::string data; };std::string temp = "Hello"; MyString myString(std::move(temp)); // 将temp的所有权转移到myString对象中
-
模板别名(template alias):
template<typename T, typename U> using Pair = std::pair<T, U>; // 定义模板别名Pair,代表std::pair<T, U>Pair<int, std::string> myPair(1, "apple"); // 使用模板别名创建Pair对象
-
可变参数模板(variadic templates):
// 使用可变参数模板实现递归求和 template<typename T> T sum(T value) {return value; }template<typename T, typename... Args> T sum(T first, Args... rest) {return first + sum(rest...); }int totalSum = sum(1, 2, 3, 4, 5); // 求和结果为15
-
类型转发(perfect forwarding):
// 完美转发函数模板 template<typename Func, typename... Args> void callFunc(Func&& func, Args&&... args) {std::forward<Func>(func)(std::forward<Args>(args)...); }// 测试函数 void printText(const std::string& str) {std::cout << str << std::endl; }std::string message = "Hello!"; callFunc(printText, message); // 将printText函数和message参数完美转发
-
std::tuple(元组):
#include <tuple> #include <iostream>int main() {std::tuple<int, std::string, double> person(25, "Alice", 1.65);int age = std::get<0>(person); // 获取元组第一个元素std::string name = std::get<1>(person); // 获取元组第二个元素double height = std::get<2>(person); // 获取元组第三个元素std::cout << "Age: " << age << std::endl;std::cout << "Name: " << name << std::endl;std::cout << "Height: " << height << std::endl;return 0; }
-
std::chrono(时间处理):
#include <chrono> #include <thread> #include <iostream>int main() {// 计算程序执行时间auto start = std::chrono::high_resolution_clock::now(); // 记录起始时间std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作,暂停2秒钟auto end = std::chrono::high_resolution_clock::now(); // 记录结束时间auto duration = std::chrono::duration_cast<std::chrono::seconds>(end - start); // 计算时间差std::cout << "Program execution time: " << duration.count() << " seconds." << std::endl;return 0; }
-
委托构造函数(delegating constructors):
#include <iostream>class Rectangle { public:Rectangle(int width, int height) : width(width), height(height) {}Rectangle(int size) : Rectangle(size, size) {} // 委托构造函数,调用其他构造函数void printArea() {std::cout << "Area: " << width * height << std::endl;}private:int width;int height; };int main() {Rectangle square(5); // 创建一个边长为5的正方形square.printArea(); // 输出面积return 0; }
-
正则表达式支持(std::regex):
#include <iostream> #include <regex>int main() {std::string text = "Hello, my email is example@example.com";std::regex pattern(R"([\w\.-]+)@([\w\.-]+)(\.\w+)"); // 匹配邮箱地址的正则表达式模式std::smatch matches;if (std::regex_search(text, matches, pattern)) { // 搜索匹配项std::cout << "Email found: " << matches.str() << std::endl;}return 0; }
这些示例展示了C++11引入的一些有用的库和特性的基本用法。std::tuple提供了一个灵活的容器,可以存储多个元素。std::chrono提供了时间处理功能,方便进行时间相关的操作和测量。委托构造函数允许一个构造函数调用另一个构造函数来初始化对象。std::thread提供了多线程编程的支持,可以创建、控制和等待线程。std::regex提供了正则表达式支持,使得文本匹配和替换变得更加方便和强大。
这些示例展示了C++11引入的泛型编程增强特性的基本用法。通过模板别名,我们可以定义更简洁易读的模板名称。可变参数模板使得编写接受可变数量参数的函数变得更加简单和灵活。类型转发允许我们在接受参数时完美地将其转发给其他函数,保留其值类别和引用类型。
这些特性都有助于提高泛型代码的可读性、灵活性和重用性,并且非常有用于编写通用库和泛型算法。
C++14
C++14 对于 C++11 进行了一些升级,主要包括以下几个方面的改进:
-
泛型 Lambda 表达式:使用泛型 lambda,可以更灵活地定义匿名函数,并且可以在函数体内使用 auto 关键字进行类型推导。
-
二进制字面量:引入了二进制字面量,可以直接表示二进制数据,例如使用 0b 前缀表示二进制数字。
-
返回类型推导:函数返回类型可以使用 auto 关键字进行推导,允许在函数定义时不显式声明返回类型。
-
constexpr 函数改进:constexpr 关键字可以用于描述函数的常量表达式特性,并且可以支持更多的操作和控制流语句。
-
运行时大小数组:允许在运行时创建具有动态大小的数组,使用 std::vector 进行管理。
-
统一的字面量语法:引入了用户自定义字面量的机制,可以自定义并使用各种单位、时间、长度等字面量。
-
一些小的语法改进:包括函数参数列表支持使用 ‘…’ 表示可变参数、更好的类型推导规则等。
总的来说,C++14 的改进主要着眼于语言的表达能力和编程的便捷性,使得程序员能够更加方便地编写高效、简洁的代码。
例子
当然,下面是一些具体的例子来说明 C++14 的一些改进:
-
泛型 Lambda 表达式:
// 使用泛型 lambda 将两个数相加并打印结果 auto add = [](auto a, auto b) {auto sum = a + b;std::cout << "Sum: " << sum << std::endl; };add(5, 10); // 输出: Sum: 15 add(3.14, 2.71); // 输出: Sum: 5.85
-
二进制字面量:
// 使用二进制字面量表示二进制数字 int binaryNumber = 0b101010; std::cout << "Binary number: " << binaryNumber << std::endl; // 输出: Binary number: 42
-
返回类型推导:
// 返回类型使用 auto 进行推导 auto add(int a, int b) {return a + b; }auto result = add(5, 10); std::cout << "Result: " << result << std::endl; // 输出: Result: 15
-
constexpr 函数改进:
// 使用 constexpr 声明常量表达式函数 constexpr int factorial(int n) {if (n <= 1)return 1;elsereturn n * factorial(n - 1); }constexpr int fact5 = factorial(5); std::cout << "Factorial of 5: " << fact5 << std::endl; // 输出: Factorial of 5: 120
-
运行时大小数组:
// 在运行时创建动态大小的数组,并使用 std::vector 进行管理 int n; std::cout << "Enter the size of the array: "; std::cin >> n;std::vector<int> dynamicArray(n); for (int i = 0; i < n; ++i) {dynamicArray[i] = i * 2; }std::cout << "Dynamic Array: "; for (auto num : dynamicArray) {std::cout << num << " "; // 输出: Dynamic Array: 0 2 4 ... } std::cout << std::endl;
-
用户自定义单位字面量:
// 自定义一个长度单位字面量 Inch constexpr long double operator"" _inch(long double inches) {return inches * 2.54; // 将英寸转换为厘米 }// 使用自定义单位字面量进行转换 long double length = 10.5_inch; std::cout << "Length in cm: " << length << std::endl; // 输出: Length in cm: 26.67
-
时间单位字面量:
// 定义一个时间单位字面量 Seconds constexpr long long operator"" _s(unsigned long long seconds) {return seconds; }// 使用时间单位字面量表示不同的时间 int main() {auto duration = 2_s;std::cout << "Duration in seconds: " << duration << std::endl; // 输出: Duration in seconds: 2auto timeout = 30_s;std::cout << "Timeout in seconds: " << timeout << std::endl; // 输出: Timeout in seconds: 30return 0; }
这些例子展示了 C++14 的一些特性和改进,使得代码更加灵活和便捷。
C++17
C++17 相对于 C++14 进行了一些重要的升级和改进。以下是其中的一些主要特性:
-
结构化绑定(Structured Bindings):允许从复合类型(如 std::tuple 或数组)中提取成员,并将其绑定到命名的变量上。
std::pair<int, std::string> p = {10, "Hello"};// 使用结构化绑定将 pair 中的成员绑定到变量中 auto [x, str] = p;std::cout << "x: " << x << std::endl; // 输出: x: 10 std::cout << "str: " << str << std::endl; // 输出: str: Hello
-
if 与 switch 初始化(if and switch with initializer):允许在 if 语句和 switch 语句中声明并初始化变量。
if (int x = computeValue(); x > 0) {// 使用 x 进行操作 }switch (int x = computeValue(); x) {case 1:// 处理 x = 1 的情况break;case 2:// 处理 x = 2 的情况break;default:// 其他情况break; }
-
强制拷贝消除(constexpr if):通过在编译时判断条件来消除无限递归和无用的代码分支。
template <typename T> void process(T value) {if constexpr (std::is_integral_v<T>) {// 对整型进行处理} else if constexpr (std::is_floating_point_v<T>) {// 对浮点型进行处理} else {// 其他类型的处理} }
-
折叠表达式(Fold Expressions):允许以一种简洁的方式展开多个参数的组合表达式。
template<typename... Args> auto sum(Args... args) {return (args + ...); }int result = sum(1, 2, 3, 4); // 等价于 result = ((1 + 2) + 3) + 4 std::cout << "Result: " << result << std::endl; // 输出: Result: 10
-
并行算法库(Parallel Algorithms Library):引入了一组新的并行算法,例如
std::for_each
、std::transform
等,并且可以利用多核处理器并行执行操作。std::vector<int> numbers = {1, 2, 3, 4, 5};// 使用并行算法计算所有元素的平方 std::for_each(std::execution::par, numbers.begin(), numbers.end(), [](int& num) {num = num * num; });
-
std::optional
:引入了一个新的标准库类型std::optional
,用于表示可能存在或不存在的值。#include <optional> #include <iostream>std::optional<int> divide(int a, int b) {if (b != 0) {return a / b;} else {return std::nullopt; // 表示不存在的值} }int main() {auto result1 = divide(10, 5);if (result1.has_value()) {std::cout << "Result1: " << result1.value() << std::endl; // 输出: Result1: 2}auto result2 = divide(10, 0);if (!result2.has_value()) {std::cout << "Cannot divide by zero." << std::endl; // 输出: Cannot divide by zero.}return 0; }
-
类模板参数推导(Class Template Argument Deduction):允许在创建类实例时省略模板参数,编译器会根据构造函数参数进行推导。
template<typename T> struct MyContainer {MyContainer(T value) {// 构造函数逻辑} };MyContainer container(42); // 省略了模板参数,编译器根据构造函数参数推导出 T 为 int 类型
-
std::string_view
:引入了一个非拥有性的字符串视图类型std::string_view
,用于高效地操作字符串而无需进行拷贝。#include <string_view> #include <iostream>void processString(std::string_view str) {std::cout << "Length: " << str.length() << std::endl;std::cout << "First character: " << str[0] << std::endl; }int main() {std::string myString = "Hello, World!";processString(myString); // 可以传递 std::string 或字符数组等给函数processString("Hello, View!"); // 也可以直接传递字符串字面量return 0; }
-
内联变量(Inline Variables):允许在头文件中定义内联变量,避免重定义错误和链接错误。
// header.h inline int value = 42;// source.cpp #include "header.h" #include <iostream>int main() {std::cout << "Value: " << value << std::endl; // 输出: Value: 42value = 10; // 修改内联变量的值std::cout << "Value: " << value << std::endl; // 输出: Value: 10return 0; }
-
结构化绑定与元组遍历:结合使用结构化绑定和
std::tie
,可以方便地遍历和访问元组成员。#include <tuple> #include <iostream>int main() {std::tuple<int, std::string, double> person = {25, "Alice", 170.5};// 使用结构化绑定遍历和访问元组成员for (const auto& [age, name, height] : {person}) {std::cout << "Age: " << age << std::endl; // 输出: Age: 25std::cout << "Name: " << name << std::endl; // 输出: Name: Alicestd::cout << "Height: " << height << std::endl; // 输出: Height: 170.5}return 0; }
-
类型特征检查(Type Traits):引入了一些新的类型特征检查工具,例如
std::is_invocable
、std::is_swappable
等,用于在编译时进行类型特性判断。#include <type_traits> #include <iostream>template<typename T> void process(T value) {if constexpr (std::is_integral_v<T>) {std::cout << "Integral type" << std::endl;} else if constexpr (std::is_floating_point_v<T>) {std::cout << "Floating-point type" << std::endl;} else {std::cout << "Other type" << std::endl;} }int main() {process(42); // 输出: Integral typeprocess(3.14); // 输出: Floating-point typeprocess("Hello"); // 输出: Other typereturn 0; }
-
内联命名空间(Inline Namespace):允许在现有的命名空间内添加内联命名空间,用于版本管理和向后兼容。
namespace math {inline namespace v1 {int add(int a, int b) {return a + b;}}inline namespace v2 {double add(double a, double b) {return a + b;}} }int main() {int result1 = math::add(2, 3); // 调用 math::v1::add,返回 5double result2 = math::add(2.5, 3.7); // 调用 math::v2::add,返回 6.2return 0; }
-
std::any
:std::any
是一个类型安全的、堆内存分配的通用值容器,可以存储任意类型的值。#include <any> #include <iostream>int main() {std::any value;// 存储不同类型的值value = 42;std::cout << std::any_cast<int>(value) << std::endl; // 输出: 42value = "Hello";std::cout << std::any_cast<const char*>(value) << std::endl; // 输出: Helloreturn 0; }
-
std::filesystem
:std::filesystem
提供了一组用于操作文件系统的功能,包括路径操作、文件查找、迭代目录等。#include <filesystem> #include <iostream>namespace fs = std::filesystem; // 别名空间简化int main() {// 读取当前目录并打印所有文件和目录的名称fs::path currentPath = fs::current_path();for (const auto& entry : fs::directory_iterator(currentPath)) {std::cout << entry.path().filename() << std::endl;}return 0; }
-
std::variant
:std::variant
是一个类型安全的、多态的联合类型,可以存储多个可能的类型之一。#include <variant> #include <iostream> #include <string>int main() {std::variant<int, double, std::string> value;value = 42;std::cout << std::get<int>(value) << std::endl; // 输出: 42value = 3.14;std::cout << std::get<double>(value) << std::endl; // 输出: 3.14value = "Hello";std::cout << std::get<std::string>(value) << std::endl; // 输出: Helloreturn 0; }
这些是 C++17 中的一些主要升级和改进。C++17 还包含了其他一些特性,例如文件系统库、更好的类型推导、内联变量、抛出异常的属性说明符等等,这些特性都进一步提高了 C++ 的功能和表达能力。
C++20
C++20 是 C++ 标准的最新版本,于 2020 年发布。它引入了一些重要的特性和改进,如以下所示:
-
概念(Concepts):概念是类型的约束,可用于在编译时验证模板参数的属性。概念使得模板更易于使用和调试,并提供更好的错误消息。
-
三路比较操作符(Three-Way Comparison):引入了
<=>
操作符,用于进行三路比较。这个操作符返回一个表示比较结果的值,可以方便地进行对象的等于、大于和小于比较。 -
协程(Coroutines):协程是一种轻量级的并发编程机制,允许在函数中暂停和恢复执行。协程通过
co_await
和co_yield
等关键字实现。 -
初始化列表的聚合推导(Aggregate Initialization with
auto
):现在可以使用auto
推导类型进行初始化列表的聚合初始化。 -
合并了
std::filesystem
库:std::filesystem
库已经成为 C++20 的一部分,提供了更强大、更便捷的文件系统操作功能。 -
Ranges 库:引入了 Ranges 库,提供了一组用于处理和操作迭代器范围的标准算法和工具函数。
-
数字分隔符(Digit Separators):可以在数字常量中使用分隔符
_
来提高可读性,例如1'000'000
。 -
其他语言改进:如对模块化编程的支持、对属性(Attribute)的增强、对线程的改进等。
这些是 C++20 中的一些重要改进和特性。C++20 的目标是提供更简洁、更安全、更高效的编程体验,并为现代软件开发带来更多的功能和灵活性。
例子
当然!以下是 C++20 中一些重要特性的示例:
-
概念(Concepts):
template <typename T> concept Integral = std::is_integral<T>::value;template <Integral T> void printNumber(T number) {std::cout << number << std::endl; }int main() {printNumber(42); // 编译通过,T 要求是整型printNumber(3.14); // 编译错误,T 不满足 Integral 概念return 0; }
-
三路比较操作符(Three-Way Comparison):
#include <iostream> #include <compare>struct Point {int x, y;auto operator<=>(const Point& other) const {return std::tie(x, y) <=> std::tie(other.x, other.y);} };int main() {Point p1{1, 2};Point p2{3, 4};auto result = p1 <=> p2;if (result < 0) {std::cout << "p1 is less than p2" << std::endl;} else if (result > 0) {std::cout << "p1 is greater than p2" << std::endl;} else {std::cout << "p1 is equal to p2" << std::endl;}return 0; }
-
协程(Coroutines):
#include <iostream> #include <coroutine>struct Generator {struct promise_type {int current_value;auto initial_suspend() { return std::suspend_always{}; }auto final_suspend() noexcept { return std::suspend_always{}; }auto yield_value(int value) {current_value = value;return std::suspend_always{};}auto return_void() {}Generator get_return_object() { return Generator{this}; }};struct iterator {std::coroutine_handle<promise_type> coroutine;iterator& operator++() {coroutine.resume();if (coroutine.done()) {coroutine.destroy();}return *this;}int operator*() const {return coroutine.promise().current_value;}bool operator==(std::default_sentinel_t) const {return coroutine.done();}};explicit Generator(promise_type* promise) :coroutine(std::coroutine_handle<promise_type>::from_promise(*promise)) {}~Generator() {if (coroutine) {coroutine.destroy();}}iterator begin() {coroutine.resume();return iterator{coroutine};}std::default_sentinel_t end() {return std::default_sentinel;}std::coroutine_handle<promise_type> coroutine; };Generator generateNumbers() {co_yield 1;co_yield 2;co_yield 3; }int main() {for (auto num : generateNumbers()) {std::cout << num << std::endl;}return 0; }
-
初始化列表的聚合推导(Aggregate Initialization with
auto
):#include <iostream> #include <vector>int main() {auto numbers = {1, 2, 3, 4, 5}; // 推导为 std::initializer_list<int>for (auto num : numbers) {std::cout << num << " ";}std::cout << std::endl;return 0; }
-
合并了
std::filesystem
库:#include <iostream> #include <filesystem>int main() {std::filesystem::path currentPath = std::filesystem::current_path();std::cout << "Current Path: " << currentPath << std::endl;if (std::filesystem::exists(currentPath)) {std::cout << "Path exists." << std::endl;}return 0; }
-
Ranges 库:
#include <iostream> #include <vector> #include <ranges>int main() {std::vector<int> numbers{1, 2, 3, 4, 5};auto evenNumbers = numbers | std::views::filter([](int num) { return num % 2 == 0; });for (auto num : evenNumbers) {std::cout << num << " ";}std::cout << std::endl;return 0; }
-
数字分隔符(Digit Separators):
#include <iostream>int main() {int million = 1'000'000;long long billion = 10'000'000'000;std::cout << "Million: " << million << std::endl;std::cout << "Billion: " << billion << std::endl;return 0; }
-
模块(Modules):
// math.cppm export module math;export int add(int a, int b) {return a + b; }// main.cpp import math;int main() {int result = add(2, 3);// 其他操作return 0; }
-
std::span
类型:#include <iostream> #include <vector> #include <span>void printValues(std::span<int> values) {for (const auto& value : values) {std::cout << value << " ";}std::cout << std::endl; }int main() {std::vector<int> numbers{1, 2, 3, 4, 5};printValues(numbers);return 0; }
这些示例展示了 C++20 中概念、三路比较操作符和协程的用法,它们是 C++20 中引入的一些重要特性,为开发者带来了更多的便利性和表达能力。当然,还有其他特性在 C++20 中,这里只是列举了一部分示例。
相关文章:
C++简介
文章目录 C简介C版本C11例子 C14例子 C17C20例子 C简介 C是一种高级编程语言,它是对C语言的扩展和增强。C由Bjarne Stroustrup于1980年发明,主要用于系统级编程、游戏开发、嵌入式系统等领域。 C具有许多特性,其中最重要的是面向对象编程&a…...
【广州华锐互动】3D空间编辑器:一款简洁易用的VR/3D在线编辑工具
随着虚拟现实技术的不断发展,数字孪生技术的应用已经被广泛应用于产品设计和制作中,能充分发挥企业应用3D建模的优势,凸显了三维设计的价值,在生产阶段也能够充分发挥3D模型的作用。 如今,广州华锐互动开发的3D空间编辑…...
golang云原生项目☞redis配置
配置redis适用与golang云原生架构。包括redis与数据库一致性等重要内容 1、编写redis配置文件、使用viper读取 配置文件 db.yml redis:addr: 127.0.0.1port: 6379password: tiktokRedisdb: 0 # 数据库编号读取配置文件 var (config viper.Init("db")zapL…...
C++ malloc/free/new/delete详解(内存管理)
C malloc/free/new/delete详解(内存管理) malloc/free典型用法内存分配实现过程brk和mmap申请小于128k的内存申请大于128k的内存释放内存brk和mmap的区别 new/delete典型用法 内存分配实现过程new/delete和malloc/free的区别malloc对于给每个进程分配的内…...
SpringBoot中Mapper.xml的入参方式
在SpringBoot开发过程中,我们使用 ***Mapper.xml***Mapper.java 来封装对数据库表的 CURD 操作,正常每张表会有一组对应的文件。 一、Mapper常见用法 下面例举一个查询操作: 数据表t_sap_customer,表中有字段id、code、name、c…...
回归预测 | MATLAB实现WOA-RBF鲸鱼优化算法优化径向基函数神经网络多输入单输出回归预测(多指标,多图)
回归预测 | MATLAB实现WOA-RBF鲸鱼优化算法优化径向基函数神经网络多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现WOA-RBF鲸鱼优化算法优化径向基函数神经网络多输入单输出回归预测(多指标,多图&#…...
浅析Python爬虫ip程序延迟和吞吐量影响因素
作为一名资深的爬虫程序员,今天我们很有必要来聊聊Python爬虫ip程序的延迟和吞吐量,这是影响我们爬取效率的重要因素。这里我们会提供一些实用的解决方案,让你的爬虫程序飞起来! 网络延迟 首先,让我们来看看网络延迟对…...
【100天精通python】Day43:python网络爬虫开发_爬虫基础(urlib库、Beautiful Soup库、使用代理+实战代码)
目录 1 urlib 库 2 Beautiful Soup库 3 使用代理 3.1 代理种类 HTTP、HTTPS 和 SOCKS5 3.2 使用 urllib 和 requests 库使用代理 3.3 案例:自建代理池 4 实战 提取视频信息并进行分析 1 urlib 库 urllib 是 Python 内置的标准库,用于处理URL、发送…...
Linux:安全技术与防火墙
目录 一、安全技术 1.安全技术 2.防火墙的分类 3.防水墙 4.netfilter/iptables关系 二、防火墙 1、iptables四表五链 2、黑白名单 3.iptables命令 3.1查看filter表所有链 iptables -L 编辑3.2用数字形式(fliter)表所有链 查看输出结果 iptables -nL 3.3 清空所有链…...
Confluent kafka 异常退出rd_tmpabuf_alloc0: rd kafka topic info_new_with_rack
rd_tmpabuf_alloc0: rd kafka topic info_new_with_rack 根据网上的例子,做了一个测试程序。 C# 操作Kafka_c# kafka_Riven Chen的博客-CSDN博客 但是执行下面一行时,弹出上面的异常,闪退。 consumer.Subscribe(queueName) 解决方案&…...
最新ChatGPT网站程序源码+AI系统+详细图文搭建教程/支持GPT4.0/AI绘画/H5端/Prompt知识库
一、前言 SparkAi系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。 那么如何搭建部署AI创作ChatGPT?小编这里写一个详细图文教程吧!…...
chatGPT-对话柏拉图
引言: 古希腊哲学家柏拉图,在他的众多著作中,尤以《理想国》为人所熟知。在这部杰作中,他勾勒了一个理想的政治制度,提出了各种政体,并阐述了他对于公正、智慧以及政治稳定的哲学观点。然而,其…...
Java项目-苍穹外卖-Day04
公共字段自动填充 这些字段在每张表基本都有,手动进行填充效率低,且后期维护更改繁琐 使用到注解AOP主要 先答应一个AutoFill注解 再定义一个切面类进行通知 对应代码 用到了枚举类和反射 package com.sky.aspect; /*** 自定义切面类,…...
SQL递归获取完整的树形结构数据
在 SQL 中,WITH RECURSIVE 用于创建递归查询,它允许在查询中引用自身。这种查询通常用于处理具有层次结构的数据,例如树形结构。 以下是使用 WITH RECURSIVE 创建递归查询的一般语法: WITH RECURSIVE [alias] ([column1], [colu…...
如何使用营销活动,提升小程序用户的参与度
在当今数字化时代,小程序已成为企业私域营销的重要一环。然而,仅仅拥有小程序还不足以吸引用户的兴趣和参与。营销活动作为推动用户参与的有效手段,可以在激烈的市场竞争中脱颖而出。本文将深入探讨如何使用营销活动,提升小程序用…...
IDEA中使用Docker插件构建镜像并推送至私服Harbor
一、开启Docker服务器的远程访问 1.1 开启2375远程访问 默认的dokcer是不支持远程访问的,需要加点配置,开启Docker的远程访问 # 首先查看docker配置文件所在位置 systemctl status docker# 会输出如下内容: ● docker.service - Docker Ap…...
第7章 高性能门户首页构建
mini商城第7章 高性能门户首页构建 一、课题 高性能门户建设 二、回顾 1、了解文件存储系统的概念 2、了解常用文件服务器的区别 3、掌握Minio的应用 三、目标 1、OpenResty 百万并发站点架构 OpenResty 特性介绍 搭建OpenResty Web站点动静分离方案剖析 2、多级缓存架…...
用加持了大模型的 Byzer-Notebook 做数据分析是什么体验
Byzer-Notebook 是专门为 SQL 而研发的一款 Web Notebook。他的第一公民是 SQL,而 Jupyter 则是是以 Python 为第一公民的。 随着 Byzer 引擎对大模型能力的支持日渐完善, Byzer-Notebook 也在不自觉中变得更加强大。我和小伙伴在聊天的过程中才发现他已…...
学习设计模式之观察者模式,但是宝可梦
前言 作者在准备秋招中,学习设计模式,做点小笔记,用宝可梦为场景举例,有错误欢迎指出。 观察者模式 观察者模式定义了一种一对多的依赖关系,一个对象的状态改变,其他所有依赖者都会接收相应的通知。 所…...
课程项目设计--spring security--用户管理功能--宿舍管理系统--springboot后端
写在前面: 还要实习,每次时间好少呀,进度会比较慢一点 本文主要实现是用户管理相关功能。 前文项目建立 文章目录 验证码功能验证码配置验证码生成工具类添加依赖功能测试编写controller接口启动项目 security配置拦截器配置验证码拦截器 …...
学习设计模式之装饰器模式,但是宝可梦
装饰模式 为了不改变组件的结构,动态地扩展其功能。 通常,扩展功能通过子类进行,但是继承的方式具有静态特征,耦合度高。 意图:动态地给对象添加额外的功能 主要解决:继承方式是静态特征,扩…...
【AWS】创建IAM用户;无法登录IAM用户怎么办?错误提示:您的身份验证信息错误,请重试(已解决)
目录 0.背景问题分析 1.解决步骤 0.背景问题分析 windows 11 ,64位 我的问题情景: 首先我创建了aws的账户,并且可以用ROOT用户登录,但是在登录时选择IAM用户,输入ROOT的名字和密码,就会提示【您的身份验证…...
微服务基础知识
文章目录 微服务基础知识一、系统架构的演变1、单体应用架构2、垂直应用架构3、分布式SOA架构(1)什么是SOA(2)SOA架构 4、微服务架构5、SOA和微服务的关系(1)SOA(2)微服务架构 二、分…...
倒残差结构
倒残差结构: 倒残差结构是MobileNetV2中引入的一种设计,用于增强网络的表达能力和特征提取能力,同时保持轻量级的特点。它的核心思想是在每个瓶颈块中,先使用一个扩张卷积(Dilated Convolution)&#x…...
Docker的基本使用
Docker 概念 Docker架构 docker分为客户端,Docker服务端,仓库 客户端 Docker 是一个客户端-服务器(C/S)架构程序。Docker 客户端只需要向 Docker 服务端发起请求,服务端将完成所有的工作并返回相应结果。 Docker …...
paddlenlp安装踩坑记录
错误1 ModuleNotFoundError: No module named paddle.metric我下载paddlepaddle-gpu2.5.0.post117解决了,最开始下载的2.5.1报错,post后面的117是我的cuda版本,不要写你对应的版本号 python3 -m pip install paddlepaddle-gpu2.5.0.post117…...
微服务流程引擎:简单又灵活,实现流程全生命周期管理!
伴随着日益激烈的市场竞争,传统的办公操作已经无法满足发展需要了。如果采用微服务流程引擎加油助力,就可以帮助企业更好地管理数据资源,高效做好各种表单制作,实现高效率办公。流辰信息以市场为导向,用心钻研低代码技…...
Qt表格数据处理
概述 在Qt表格数据处理中,涉及到如下几个具体的类: QAbstractItemModel:这是一个抽象基类,定义了模型(Model)的接口规范。所有的模型类都应该派生自QAbstractItemModel,并实现它的纯虚函数&…...
EasyPOI 实战总结
EasyPOI实战总结 简介 easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员 就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板 语言(熟悉的表达式语法),完成以前复杂的写法 使用EasyPOI 环境搭建 # 1.引入相关依…...
【LeetCode-困难题】42. 接雨水
题目 题解一:暴力双重for循环(以行计算水量) 1.先找出最高的柱子有多高(max 3) 2.然后第一个for为行数(1,2,3) 3.第二个for计算每一行的雨水量(关键在于去除…...
做 爱 网站视频短片/网站设计需要什么
P25-前端基础-CSS盒子模型_内边框 1.概述 内边距(padding) 内边距的设置会影响到盒子的大小,背景颜色会延伸到内边距上。 盒子的可见框的大小,由内容区 内边距 和 边框共同决定,所以在计算盒子大小时,需要…...
怎么做同城商务网站/哈尔滨电话本黄页
目录前言环境问题描述:尝试办法1.配置启动参数(未解决)2.[修改IDEA配置](https://zhuanlan.zhihu.com/p/103850463),idea64.exe.vmoptions(未解决)3.[修改Tomcat配置](https://www.cnblogs.com/lixin-link/…...
wordpress pinboard/新闻最新热点
对比git diff命令之前,我们先新建一个test.txt文本,先后执行如下命令 # 第一次编辑文本,新增第一行内容 first content. # 执行git命令-提交到版本库 $ git add test.txt $ git commit -m "first submit" # 第二次编辑文本,新增第二…...
asp.net网站开发流程/百度搜索网
一.当前简介 版本信息 device-manage:v1.0 mysql: 5.6.20 jdk : 1.8 Apache Maven 3.3.3Spring4.2.5.RELEASSpingMVChibernate4.3.11.Final bootstrap-4.3.1 将提供的文本文件完整入库并记录每条记录入库时间 当前性能:对 24309条数据入库,耗…...
阿里云简单网站建设/快速排名工具免费查询
最近又遇到了JacvaScript中的call()方法和apply()方法,而在某些时候这两个方法还确实是十分重要的,那么就让我总结这两个方法的使用和区别吧。 1. 每个函数都包含两个非继承而来的方法:call()方法和apply()方法。 2. 相同点:这两…...
做传媒网站公司/帮人推广注册app的平台
文章目录 前言 网站访问流程(故事版) 如何排查问题 如果客户说访问web网站慢 如果你访问网站发现的确访问速度很慢,这时候你需要排查网站慢的原因 1) 检查网站服务器是否异常 2) 检查与网站相关联的服务是否异常 3&…...