C++ 新特性 | C++17 常用新特性介绍

news2025/2/22 11:04:49

目录

1、结构化绑定

2、constexpr扩展

2.1、constexpr lambda

2.2、constexpr if

2.3、constexpr string

4、if with initializer

5、std::optional

6、使用inline定义内联变量

7、std::filesystem库

8、折叠表达式

9、模板的模板参数推导

9.1、从构造函数参数推导模板参数

9.2、从函数参数推导模板参数

10、std::variant

11、std::byte

12、并行算法

12.1、std::for_each和std::for_each_n

12.2、std::transform和std::transform_reduce

12.3、std::reduce和std::inclusive_scan

12.4、std::sort和std::partial_sort


C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C/C++实战进阶(专栏文章已更新380多篇,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.htmlWindows C++ 软件开发从入门到精通(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12695902.htmlVC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795开源组件及数据库技术(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html网络编程与网络问题分享(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_2276111.html      C++17是C++标准委员会于2017年发布,其官方名称为ISO/IEC 14882:2017。C++17在C++14的基础上进行了大量改进和扩展,旨在提高编程效率、简化代码以及增强标准库的功能。下面介绍一些C++17的一些主要特性。

  • 很多C++开源库会大规模地使用C++11及以上的新特性,比如WebRTC开源库,所以在阅读开源代码时需要了解C++11及以上新特性。我们在日常编码中会用到部分新特性,比如一些新的关键字(auto、nullptr、override、final等)、lambda表达式(匿名函数)、智能指针等。此外,现在很多C++开发岗位在面试时都会问到C++11或以上的新特性方面的内容。所以学习C++11及以上的新特性很有必要!
  • C++新标准引入的诸多新特性,解决了语言上的部分缺陷,使得C++更得加高效灵活!但也使得C++变得更加臃肿复杂,更加难以驾驭!

1、结构化绑定

       可以通过一行代码将结构体或元组中的成员绑定到变量上,从而方便地访问这些成员。

struct Point 
{
    int x;
    int y;
};

Point pt{1, 2};
auto [x, y] = pt;

      在这个例子中,我们定义了一个Point结构体,并创建了一个名为pt的实例,它包含了两个成员变量x和y。接着,我们使用auto关键字和一对中括号,将x和y变量绑定到了pt的成员变量上。在这之后,我们就可以直接使用x和y变量来访问pt的成员变量了,而不需要通过pt.x和pt.y来访问。

       需要注意的是,只能在函数内部使用,不能在全局作用域中使用,结构化绑定仅适用于具有公共成员的结构体和元组类型。 此外,结构化绑定还可以在for循环中使用,从而方便地遍历数组、容器等数据结构中的元素。

std::vector<std::pair<int, std::string>> v{{1, "one"}, {2, "two"}, {3, "three"}};
for (auto [key, value] : v) 
{
    std::cout << "key: " << key << ", value: " << value << std::endl;
}

       在这个例子中,我们定义了一个vector容器,其中存储了多个pair类型的元素。在for循环中,我们使用auto关键字和一对中括号,将key和value变量绑定到了pair元素的first和second成员上。在循环体中,我们就可以直接使用key和value变量来访问pair元素的成员了。

       需要注意的是,结构化绑定在for循环中使用时,变量名的顺序应该与元素成员的顺序一致,否则会导致绑定错误。此外,需要确保绑定的变量类型与元素成员的类型一致。

2、constexpr扩展

       C++17中支持将constexpr与其他东西结合起来使用,使用起来会更加灵活。

2.1、constexpr lambda

       C++17支持将constexpr与Lambda表达式结合起来使用,主要体现在以下两点:

  • Lambda表达式支持constexpr:在C++17中,lambda表达式可以被声明为constexpr,这意味着它们可以在编译时被求值。这允许lambda表达式在需要编译时常量表达式的场合中使用,例如作为模板参数或初始化constexpr变量。
  • 条件编译时的Lambda表达式:即使lambda表达式没有被显式声明为constexpr,只要它满足constexpr的要求(如捕获的变量是字面量类型),它在编译时常量表达式中也能被隐式地视为constexpr。

       C++17中的constexpr lambda可以用于编译时计算,可以在编译时执行lambda表达式,而不需要运行时执行。

#include <iostream>

int main() 
{
    constexpr auto square = [](int x) { return x * x; };
    constexpr int result = square(5);
    std::cout << result << std::endl;
    return 0;
}

在上面的示例中,我们定义了一个constexpr lambda表达式,它接受一个整数参数并返回该参数的平方。我们还定义了一个constexpr整数变量result,它将square(5)的结果赋值给它。由于lambda表达式是constexpr的,因此square(5)将在编译时计算,而不是在运行时计算。

       需要注意的是,constexpr lambda表达式的参数和返回类型必须是字面类型,否则无法在编译时计算。


       在这里,给大家重点推荐一下我的几个热门畅销专栏,欢迎订阅:(博客主页还有其他专栏,可以去查看)

专栏1:(该精品技术专栏的订阅量已达到500多个,专栏中包含大量项目实战分析案例,有很强的实战参考价值,广受好评!专栏文章持续更新中,预计更新到200篇以上!欢迎订阅!)

C++软件调试与异常排查从入门到精通系列文章汇总icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931

本专栏根据多年C++软件异常排查的项目实践,系统地总结了引发C++软件异常的常见原因以及排查C++软件异常的常用思路与方法,详细讲述了C++软件的调试方法与手段,以图文并茂的方式给出具体的项目问题实战分析实例(很有实战参考价值),带领大家逐步掌握C++软件调试与异常排查的相关技术,适合基础进阶和想做技术提升的相关C++开发人员!

考察一个开发人员的水平,一是看其编码及设计能力,二是要看其软件调试能力!所以软件调试能力(排查软件异常的能力)很重要,必须重视起来!能解决一般人解决不了的问题,既能提升个人能力及价值,也能体现对团队及公司的贡献!

专栏中的文章都是通过项目实战总结出来的,包含大量项目问题实战分析案例,有很强的实战参考价值!专栏文章还在持续更新中,预计文章篇数能更新到200篇以上!

专栏2:  

C++常用软件分析工具从入门到精通案例集锦汇总(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795

常用的C++软件辅助分析工具有SPY++、PE工具、Dependency Walker、GDIView、Process Explorer、Process Monitor、API Monitor、Clumsy、Windbg、IDA Pro等,本专栏详细介绍如何使用这些工具去巧妙地分析和解决日常工作中遇到的问题,很有实战参考价值!

专栏3:(本专栏涵盖了多方面的内容,是当前重点打造的专栏,专栏文章已经更新到390多篇,持续更新中...)

C/C++实战进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html

以多年的开发实战为基础,总结并讲解一些的C/C++基础与项目实战进阶内容,以图文并茂的方式对相关知识点进行详细地展开与阐述!专栏涉及了C/C++领域多个方面的内容,包括C++基础及编程要点(模版泛型编程、STL容器及算法函数的使用等)、C++11及以上新特性(不仅看开源代码会用到,日常编码中也会用到部分新特性,面试时也会涉及到)、常用C++开源库的介绍与使用、代码分享(调用系统API、使用开源库)、常用编程技术(动态库、多线程、多进程、数据库及网络编程等)、软件UI编程(Win32/duilib/QT/MFC)、C++软件调试技术(排查软件异常的手段与方法、分析C++软件异常的基础知识、常用软件分析工具使用、实战问题分析案例等)、设计模式、网络基础知识与网络问题分析进阶内容等。

专栏4:   

VC++常用功能开发汇总(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585

将10多年C++开发实践中常用的功能,以高质量的代码展现出来。这些常用的高质量规范代码,可以直接拿到项目中使用,能有效地解决软件开发过程中遇到的问题。

专栏5: 

Windows C++ 软件开发从入门到精通(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12695902.html

根据多年C++软件开发实践,详细地总结了Windows C++ 应用软件开发相关技术实现细节,分享了大量的实战案例,很有实战参考价值。


2.2、constexpr if

       C++17引入了constexpr if语句,允许在编译时根据常量表达式的结果来选择性地编译代码块。这极大地改善了模板元编程中的条件编译,使得原本需要在运行时进行的选择可以在编译时完成,从而优化代码并提高执行效率。

       使用constexpr if,编译器可以只编译满足条件的代码路径,忽略不满足条件的代码路径,这有助于减少编译后的代码大小并提高运行效率。

       C++17中的constexpr if是一种条件编译语句,用于在编译时进行条件判断,从而在编译期间选择不同的代码路径。

1)在if语句中使用constexpr关键字,如果条件表达式是constexpr,则编译器在编译期间进行判断。
2)如果条件表达式为真,则编译器编译if语句中的代码块;否则,编译器忽略if语句中的代码块。
3)可以在if语句中使用else关键字,来指定条件为假时要编译的代码块。

比如下面一段代码:

template<typename T>
void print(const T& t)
{
    if constexpr (std::is_integral_v<T>)
    {
        std::cout << "Integral type: " << t << std::endl;
    }
    else if constexpr (std::is_floating_point_v<T>)
    {
        std::cout << "Floating point type: " << t << std::endl;
    }
    else
    {
        std::cout << "Unknown type: " << t << std::endl;
    }
}

int main()
{
    int i = 8;
    float f = 3.5f;
    std::string s = "Hello World";

    print(i);   // 输出 "Integral type: 8"
    print(f);   // 输出 "Floating point type: 3.5"
    print(s);   // 输出 "Unknown type: Hello World"

    return 0;
}

在上面的示例代码中,我们使用了constexpr if语句来根据传入的类型不同,选择不同的输出方式。'std::is_integral_v’是C++17中的一个模板元编程工具,用于判断一个类型是否为整数类型。它是一个类型特征(type trait),返回一个布尔值,表示传入的类型是否为整数类型。'std::is_floating_point_v’同理。

2.3、constexpr string

        C++17中引入了std::string_view和constexpr std::string这两个新特性,可以更方便地处理字符串。

       constexpr std::string是一个编译时常量字符串,可以在编译时计算,不需要在运行时再次计算。可以使用以下方式创建:

constexpr std::string str = "Hello World";

       std::string_view是一个非拥有式的字符串视图,可以用于访问字符串的子串。可以使用以下方式创建:

std::string_view str_view = "Hello World";

       非拥有式的字符串视图: 它不拥有底层字符串的内存,而是对底层字符串的一个引用或视图 。因此,它不会在自身生命周期结束时释放底层字符串的内存。使用非拥有式的字符串视图可以避免复制字符串,提高程序的性能。例如,在函数调用中传递字符串参数时,使用非拥有式的字符串视图可以避免不必要的内存复制。需要注意的是,当使用非拥有式的字符串视图时,需要确保底层字符串的生命周期不短于视图的生命周期,否则可能会导致悬垂指针的问题。

4、if with initializer

       C++17中的if with initializer是一种新的语法结构,允许在if语句中声明和初始化变量。这种语法结构的好处是可以使代码更简洁,因为变量声明和初始化可以在if语句中完成。

if (int x = some_function()) 
{
    // 如果some_function返回的值不为0,则进入if语句块
    // 变量x的作用域仅限于if语句块内部
    // 变量x的类型为int,值为some_function()的返回值
}

       在上面的示例中,if语句中声明了一个变量x,并将其初始化为some_function()的返回值。如果some_function()的返回值不为0,则进入if语句块。在if语句块之外,变量x不再可见。

       使用if with initializer可以避免在if语句之前声明变量并进行初始化的冗余代码。同时,这种语法结构还可以使代码更加清晰和简洁。

5、std::optional

       std::optional是C++17中引入的一个新特性,用于表示可以存在或不存在的值。它类似于指针,但提供了更好的语义和安全性。

#include <iostream>
#include <optional>

std::optional<int> divide(int a, int b) 
{
    if (b == 0) 
    {
        return std::nullopt; // 表示不存在值
    } 
    else 
    {
        return a / b;
    }
}

int main() {
    auto result = divide(10, 2);
    if (result) 
    {
        std::cout << "Result: " << *result << std::endl;
    } 
    else 
    {
        std::cout << "Error: Division by zero" << std::endl;
    }

    result = divide(10, 0);
    if (result) 
    {
        std::cout << "Result: " << *result << std::endl;
    } 
    else 
    {
        std::cout << "Error: Division by zero" << std::endl;
    }

    return 0;
}

在这个例子中,divide函数返回一个std::optional。如果除数为0,则返回std::nullopt表示不存在值。否则返回a/b的结果。在main函数中,我们使用if语句检查result是否存在值。如果存在,则使用*运算符获取值并输出。否则输出错误信息。

       std::optional还提供了其他一些有用的函数,例如value_or函数,用于获取值或默认值。例如:

auto result = divide(10, 0);
int value = result.value_or(-1); // 如果不存在值,则返回-1

       std::optional是一个非常有用的工具,可以避免许多指针相关的问题,并提供更好的语义和安全性。

6、使用inline定义内联变量

       在 C++17 中,可以使用 inline 关键字来定义内联变量。内联变量的定义必须在头文件中,并且不能有初始化器。

// 头文件 example.h
inline int x; // 声明内联变量

// 源文件 example.cpp
#include "example.h"
int x = 42; // 定义内联变量

// 在使用内联变量时,可以直接使用其名称,就像使用普通变量一样:
#include "example.h"
int main() 
{
    x = 10; // 直接使用内联变量 x
    return 0;
}

需要注意的是,内联变量的使用和内联函数的使用有些不同。内联函数的定义必须在每个使用它的编译单元中都可见,否则会导致链接错误。而内联变量的定义只需要在任意一个编译单元中可见即可,因为它们不会导致多个实例的生成。

7、std::filesystem库

       C++17中引入了std::filesystem库,用于处理文件系统操作。文件操作的函数很多,在此举例,可以自行查找文档。说一下相比于以前的文件操作的优势:

  • 更加简洁易用:std::filesystem库提供了一组简洁易用的函数和类,能够方便地完成常见的文件系统操作,使代码更加简洁易读。
  • 跨平台支持:std::filesystem库能够跨平台支持各种操作系统,包括Windows、Linux、macOS等操作系统,因此可以在不同的平台上使用相同的代码。
  • 更好的性能:std::filesystem库的实现使用了现代操作系统的一些高效API,能够更好地利用操作系统的缓存和异步I/O机制,从而提高文件操作的性能。
  • 更好的错误处理:std::filesystem库提供了一组异常类,能够更好地处理文件操作中可能出现的错误,从而使代码更加健壮。

8、折叠表达式

       折叠表达式是C++17中引入的新特性,用于简化模板元编程和可变参数模板的实现。折叠表达式允许在编译时对一系列参数进行折叠操作,最终得到一个值。折叠表达式的语法如下:

( pack op ... op init )
( init op ... op pack )
( ... op pack )
( pack op ... op )

其中,pack是可变参数列表中的参数,op是操作符,init是初始值。其中第三种和第四种语法需要至少有一个参数。

       例如,以下代码使用折叠表达式计算可变参数列表中的所有值之和:

template<typename... Args>
auto sum(Args... args) 
{
    return (args + ...); // 折叠表达式
}

int main()
{
    int s = sum(1, 2, 3, 4, 5); // s = 15
    return 0;
}

在这个例子中,(args + ...)表示对所有可变参数进行求和操作。折叠表达式会将所有参数依次展开,然后通过加法运算符对它们进行累加,最终得到结果。

9、模板的模板参数推导

       在C++17中,类模板的模板参数推导被引入,允许我们在使用类模板时省略模板参数列表中的一些参数,而让编译器根据上下文自动推导。

9.1、从构造函数参数推导模板参数

template<typename T>
class MyVector 
{
public:
    MyVector(std::initializer_list<T> list) 
    {
        // ...
    }
};

MyVector vec = {1, 2, 3};

在这个例子中,我们没有显式指定MyVector的模板参数,但编译器可以从std::initializer_list中的元素类型T推导出它的类型为MyVector。

9.2、从函数参数推导模板参数

template<typename T>
class MyArray 
{
public:
    T& operator[](std::size_t index) 
    {
        // ...
    }
};

void foo(MyArray<int> arr) 
{
    // ...
}

MyArray arr = {1, 2, 3};
foo(arr);

在这个例子中,我们也没有显式指定MyArray的模板参数,但编译器可以从foo函数的参数类型MyArray推导出它的类型为MyArray。

       需要注意的是,类模板的模板参数推导只能用于构造函数和函数参数,不能用于类模板的成员函数或者静态成员变量。另外,模板参数推导只能用于单一的模板参数,不能同时推导多个模板参数。

10、std::variant

       学过QT的对这个关键字想必很熟悉,C++17中的std::variant是一种类型安全的联合类型,它可以存储多个不同的类型值。在使用std::variant时,需要包含头文件。std::variant的声明方式如下:

std::variant<int, double, std::string> v;

这里声明了一个std::variant对象v,它可以存储int、double和std::string类型的值。初始时,v中没有值。

       可以通过std::get函数从std::variant对象中获取值,例如:

v = 3.55;
double d = std::get<double>(v);

这里将3.55赋值给v,然后通过std::get函数获取v中的double值,并将其赋值给变量d。

       当std::variant对象中存储的值类型与std::get函数传入的类型不匹配时,将抛出std::bad_variant_access异常。

       可以使用std::visit函数访问std::variant对象中的值。std::visit函数接受一个lambda表达式作为参数,该lambda表达式的参数类型是std::variant对象中存储的所有类型。例如:

std::visit([](auto&& arg) 
{
    std::cout << arg << std::endl;
}, v);

这里访问v中存储的值,并将其输出到控制台。lambda表达式的参数类型是auto&&,表示可以接受任意类型的参数。

       std::variant还提供了一些其他的方法,例如std::holds_alternative函数可以判断std::variant对象中是否存储了指定类型的值,std::index_sequence_for函数可以获取std::variant模板参数中类型的数量等。

       总的来说,std::variant提供了一种灵活、类型安全的联合类型实现方式,可以帮助我们更方便地处理多种不同类型的值。

11、std::byte

       C++17中的std::byte是一个新类型,用于表示字节数据。它是一种无符号整数类型,有8个比特位,可以表示0到255之间的值。与其他整数类型不同,std::byte类型没有定义任何算术运算符,因为它们不是数学上的对象,而是表示二进制数据的字节。

       使用std::byte类型可以更好地处理二进制数据,因为它提供了更直观和类型安全的方式来表示字节。例如,可以使用std::byte类型来读写二进制文件、网络数据包等:

#include <iostream>
#include <cstddef>

int main()
{
    std::byte b1{0x12};
    std::byte b2{0xff};

    // 比较两个std::byte类型的值
    if (b1 == b2) 
    {
        std::cout << "b1 and b2 are equal" << std::endl;
    } 
    else 
    {
        std::cout << "b1 and b2 are not equal" << std::endl;
    }

    // 将std::byte类型转换为整数类型
    std::size_t n = static_cast<std::size_t>(b1);
    std::cout << "n = " << n << std::endl;

    // 使用std::byte类型处理二进制数据
    std::byte buffer[1024];
    // 从文件中读取二进制数据到缓冲区
    // ...

    // 将缓冲区中的数据发送到网络
    // ...
}

12、并行算法

       C++17中提供了一些新的并行算法,可以使用这些算法来实现并行化的计算。这些算法都在头文件== < execution > ==中定义,使用前需要包含该头文件。以下是使用C++17并行算法的一些示例。

12.1、std::for_each和std::for_each_n

       std::for_each和std::for_each_n可以用于并行地遍历一个序列,对每个元素进行操作。

#include <algorithm>
#include <execution>
#include <vector>

int main() 
{
    std::vector<int> v{1, 2, 3, 4, 5};

    // 并行遍历
    std::for_each(std::execution::par, v.begin(), v.end(), [](int& x) {
        x *= 2;
    });

    // 并行遍历前3个元素
    std::for_each_n(std::execution::par, v.begin(), 3, [](int& x) {
        x *= 2;
    });
}

12.2、std::transform和std::transform_reduce

       std::transform可以用于并行地对一个序列进行变换操作,std::transform_reduce可以用于并行地对一个序列进行变换操作并求和。

#include <algorithm>
#include <execution>
#include <vector>

int main() 
{
    std::vector<int> v{1, 2, 3, 4, 5};

    // 并行变换
    std::vector<int> result(v.size());
    std::transform(std::execution::par, v.begin(), v.end(), result.begin(), [](int x) {
        return x * 2;
    });

    // 并行变换并求和
    int sum = std::transform_reduce(std::execution::par, v.begin(), v.end(), 0, std::plus<int>{}, [](int x) {
        return x * 2;
    });
}

12.3、std::reduce和std::inclusive_scan

       std::reduce可以用于并行地对一个序列求和,std::inclusive_scan可以用于并行地对一个序列进行前缀和。

#include <algorithm>
#include <execution>
#include <vector>

int main() 
{
    std::vector<int> v{1, 2, 3, 4, 5};

    // 并行求和
    int sum = std::reduce(std::execution::par, v.begin(), v.end());

    // 并行前缀和
    std::vector<int> result(v.size());
    std::inclusive_scan(std::execution::par, v.begin(), v.end(), result.begin());
}

12.4、std::sort和std::partial_sort

       std::sort可以用于并行地对一个序列进行排序,std::partial_sort可以用于并行地对一个序列的前N个元素进行排序。

#include <algorithm>
#include <execution>
#include <vector>

int main() 
{
    std::vector<int> v{5, 3, 1, 4, 2};

    // 并行排序
    std::sort(std::execution::par, v.begin(), v.end());

    // 并行部分排序
    std::partial_sort(std::execution::par, v.begin(), v.begin() + 3, v.end());
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1996734.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

景联文科技:破解数据标注行业痛点,引领高质量AI数据服务

数据标注行业是人工智能和机器学习领域中一个非常重要的组成部分。随着AI技术的发展&#xff0c;对高质量标注数据的需求也在不断增长。 数据标注市场的痛点 1. 团队管理 在众包和转包模式下&#xff0c;管理大量的标注人员是一项挑战。 需要确保标注人员的专业性、稳定性和…

【ConcurrentHashMap】JDK1.7版本源码解读与分析

如果对文章中提到的与 HashMap 相关的部分有任何疑问, 请移步HashMap源码详解 简介 底层是一个 Segment[] 数组, 每个 Segment对象 内部又有一个 Entry[ ] 数组, 一个 Entry[] 数组就相当于一个HashMap Entry[ ]采用拉链法解决冲突, 但是没有红黑树, 红黑树是1.8才引入的; 一…

音频进阶学习一——模拟信号和数字信号

文章目录 前言|版本声明&#xff1a;山河君&#xff0c;未经博主允许&#xff0c;禁止转载 一、什么是模拟信号和数字信号信号模拟信号数字信号数字和模拟信号的区别一览 二、信号处理系统总结 前言 所有软件的运行都得益于硬件上的突破&#xff0c;数字信号是从40年前就开始高…

达梦数据库 物理备份还原

达梦的物理备份还原 1.背景2.要求3.实验步骤3.1 相关术语3.2 准备工作3.3 联机备份还原3.3.1 数据备份3.3.1.1 手动备份3.3.1.2 定时备份 3.3.2 管理备份3.3.2.1 备份目录管理3.3.2.2 备份集校验与删除 3.3.3 数据还原 3.4 脱机备份还原3.4.1 DMRMAN工具3.4.2 数据备份3.4.2.1 …

https://ffmpeg.org/

https://ffmpeg.org/ https://www.gyan.dev/ffmpeg/builds/ https://github.com/BtbN/FFmpeg-Builds/releases F:\Document_ffmpeg F:\Document_ffmpeg\ffmpeg-master-latest-win64-gpl-shared\bin

python模式设计代码之观察者模式

1、观察者模式 话题订阅模式。观察者模式有两个角色&#xff0c;分别是话题发布者和话题订阅者&#xff08;即观察者&#xff09;。发布者就是把消息发送给话题&#xff0c;观察者就是订阅这个话题从而得到最新的资讯。这个模式的作用就拿手机的消息推送来说&#xff0c;app身…

深入C# .NET核心:委托与事件机制全解析

摘要&#xff1a; 在C# .NET编程中&#xff0c;委托和事件是实现异步编程和对象间通信的关键机制。理解它们的工作原理对于编写高效、响应式的应用程序至关重要。本文将深入探讨C# .NET中的委托与事件&#xff0c;从基础概念到高级应用&#xff0c;为读者提供全面的指导。 正文…

如何提高游戏的可玩性和趣味性?

提高游戏的可玩性和趣味性是吸引玩家并保持他们长期参与的关键。以下是一些策略和建议&#xff0c;可以帮助您增强游戏的吸引力和娱乐价值&#xff1a; 1. 独特的游戏机制 创新玩法&#xff1a;开发新颖、独特的游戏机制&#xff0c;让玩家在体验中感受到前所未有的乐趣。避免…

【网络编程】字节序,IP地址、点分十进制、TCP与UDP的异同

记录学习&#xff0c;思维导图绘制 目录 1、字节序​编辑 2、IP地址 3、点分十进制 4、TCP与UDP的异同 1、字节序 2、IP地址 3、点分十进制 4、TCP与UDP的异同

STL源码刨析:红黑树(RB-tree)

目录 1.前言 2.RB-tree的简单介绍 3.RB-tree的插入节点操作 4.RB-tree的删除节点操作 5.RB-tree的节点设计 6.RB-tree的迭代器设计 7.RB-tree的数据结构 8.RB-tree的构造与内存管理 9.RB-treed的元素操作 前言 在文章《STL源码刨析&#xff1a;树的导览》中&#xff0c;曾简单的…

使用 MongoDB 构建 AI:Flagler Health 的 AI 旅程如何彻底改变患者护理

Flagler Health 致力于为慢性病患者提供支持&#xff0c;为其匹配合适的医生以提供合适的护理。 通常&#xff0c;身患严重病痛的患者面临的选择有限&#xff0c;他们往往需要长期服用阿片类药物&#xff0c;或寻求成本高昂的侵入性外科手术干预。遗憾的是&#xff0c;后一种方…

linux小组件:git

git是什么&#xff1f; git是版本控制器&#xff08;去中心化的分布式系统&#xff09;可以快速高效地处理从小型到大型的各种项目。易于学习&#xff0c;占地面积小&#xff0c;性能极快。它具有廉价的本地库&#xff0c;方便的暂存区域和多个工作流分支等特性。 什么叫版本…

【数据结构七夕专属版】单链表及单链表的实现【附源码和源码讲解】

本篇是博主在学习数据结构时的心得&#xff0c;希望能够帮助到大家&#xff0c;也许有些许遗漏&#xff0c;但博主已经尽了最大努力打破信息差&#xff0c;如果有遗漏还请见谅&#xff0c;嘻嘻&#xff0c;前路漫漫&#xff0c;我们一起前进&#xff01;&#xff01;&#xff0…

微信小程序--19(.wxml 模板文件简单归纳)

类似HTML用来描述当前页面的结构 一、普通样式 1.<view> 内容 </view> 二、滚波样式 1.<swiper> 内容 </swiper> 2.<swiper-item>滚波内容 </swiper-item> 3.常用属性 纵向&#xff1a;scroll-y横向&#xff1a;scroll-x圆点颜色&am…

LinuxC高级day03(Shell脚本)

【1】Shell脚本 1》Shell脚本基础概念 1> 概念 Shell使用方式&#xff1a;手动在命令行下命令或用Shell脚本 Shell脚本本质&#xff1a;Shell命令的有序集合 扩展名最好以 .sh 结尾&#xff0c;见名知义 也可以没有 Shell既是应用程序&#xff0c;又是一种脚本语言 解…

迁移学习之基本概念

迁移学习 1、通俗定义 迁移学习是一种学习的思想和模式 迁移学习作为机器学习的一个重要分支&#xff0c;侧重于将已经学习过的知识迁移应用于新的问题中 迁移学习的核心问题是&#xff0c;找到新问题和原问题之间的相似性&#xff0c;才可以顺利地实现知识地迁移 定义&…

运行pytorch报异常处理

一、问题现象及初步定位&#xff1a; 找不到指定的模块。 Error loading "D:\software\python3\Lib\site-packages\torch\lib\fbgemm.dll 此处缺少.dll文件&#xff0c;首先下载文件依赖分析工具 Dependencies https://github.com/lucasg/Dependencies/tree/v1.11.1 之后下…

leetcode169. 多数元素,摩尔投票法附证明

leetcode169. 多数元素 给定一个大小为 n 的数组 nums &#xff0c;返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 示例 1&#xff1a; 输入&#xff1a;nums [3,2,3] 输…

C# winform 三层架构 增删改查 修改数据(修改篇)

ss一.留言 本专栏三层架构已经更新了 添加 登录 显示&#xff0c;还差修改以及删除&#xff0c;本篇更新修改&#xff0c;主要操作为点击修改某一条数据&#xff0c;然后跳转页面进行修改。 二.展示 我们先看DAL代码 /// <summary>/// 修改/// </summary>/// &l…

【RTOS面试题】什么是抢占?抢占的原理、抢占的好处、抢占有什么局限性?

&#x1f48c; 所属专栏&#xff1a;【RTOS-操作系统-面试题】 &#x1f600; 作  者&#xff1a; 于晓超 &#x1f680; 个人简介&#xff1a;嵌入式工程师&#xff0c;专注嵌入式领域基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大家&#xf…