【C++篇】C++类与对象深度解析(六):全面剖析拷贝省略、RVO、NRVO优化策略

news2024/11/14 14:25:58

文章目录

  • C++类与对象
    • 前言
    • 读者须知
      • RVO 与 NRVO 的启用条件
      • 如何确认优化是否启用?
    • 1. 按值传递与拷贝省略
      • 1.1 按值传递的概念
      • 1.2 示例代码
      • 1.3 按值传递的性能影响
        • 1.3.1 完全不优化
      • 1.4 不同编译器下的优化表现
        • 1.4.1 Visual Studio 2019普通优化
        • 1.4.2 Visual Studio 2022激进优化
      • 1.5 小结
    • 2. 返回值优化(RVO)
      • 2.1 RVO 的概念
      • 2.2 示例代码
      • 2.3 不同优化下的表现
        • 2.3.1 完全不优化的情况
        • 2.3.2 启用 RVO 的情况(Visual Studio 2019)
        • 2.3.3 激进 RVO 的情况(Visual Studio 2022)
      • 2.4 小结
    • 3. 命名返回值优化(NRVO)
      • 3.1 NRVO 的概念
      • 3.2 示例代码
      • 3.3 优化下的不同表现
        • 3.3.1 完全不优化的情况
        • 3.3.2 启用 NRVO 的情况(Visual Studio 2019 和 2022)
      • 3.4 Visual Studio 2022 的优化对比
      • 3.5 小结
    • 4. 赋值操作无法优化的原因
      • 4.1 赋值操作的本质
      • 4.2 示例代码
    • 5. Visual Studio 2019 vs Visual Studio 2022 编译器优化差异
      • 5.1 编译器的工作原理
      • 5.2 为什么 VS2022 更加激进?
      • 5.3 编译器的激进优化总结
    • 6. 总结

C++类与对象

前言

💬 欢迎讨论:如果你在学习过程中有任何问题或想法,欢迎在评论区留言,我们一起交流学习。你的支持是我继续创作的动力!

👍 点赞、收藏与分享:觉得这篇文章对你有帮助吗?别忘了点赞、收藏并分享给更多的小伙伴哦!你们的支持是我不断进步的动力! 🚀
分享给更多人:如果你觉得这篇文章对你有帮助,欢迎分享给更多对C++感兴趣的朋友,让我们一起进步!

C++ 作为一门底层高效语言,在设计时便考虑到了性能和资源管理。程序员在编写代码时,常常面临对象的频繁创建与销毁,尤其是在函数返回值的传递过程中,可能会触发多次对象的拷贝构造或移动操作。为了减少这些不必要的拷贝,C++ 编译器会采用一些优化技术,如 拷贝省略(Copy Elision)、返回值优化(Return Value Optimization,RVO)和 命名返回值优化(Named Return Value Optimization,NRVO)。

读者须知

RVO 与 NRVO 的启用条件

虽然 RVO 和 NRVO 是编译器自动完成的优化,但是这些优化并不总是启用,具体取决于编译器的实现和配置。例如:

  • C++17 之前,RVO 是一个可选优化,但在 C++17 标准之后,RVO 被强制启用,编译器必须在符合条件的情况下执行拷贝省略。
  • NRVO 通常依赖于编译器的智能分析,虽然大多数现代编译器都能支持 NRVO,但其效果和激进程度因编译器和版本的不同而有所差异。

因此,尽管 RVO 是 C++ 标准的一部分,但 NRVO 则并不总是强制执行,尤其是在复杂场景下,不同的编译器版本可能表现出不同的优化行为。

如何确认优化是否启用?

你可以通过编译时的优化级别和编译器选项来控制 RVO 和 NRVO 的启用。通常使用 -O2-O3 优化级别可以启用这些优化。如果你希望查看编译器具体是否执行了这些优化,可以通过以下方式进行检查:

  • GCC:使用 -fno-elide-constructors 禁用拷贝省略。
  • Clang:通过 -fno-elide-constructors 禁用拷贝省略。
  • MSVC:Visual Studio 中可以通过 /Od(禁用优化)或 /O2(启用优化)控制优化行为。

在本篇中主要使用VS2019和VS2022来进行比较,因为实际情况的复杂性,以及编译器版本的不同,甚至同一大版本中小版本的不同更新的VS都存在一定的差异,本篇输出结果示例仅作参考,更多的是让读者通过不同优化的比较来理解现代编译器在提升程序效率所做的改进


1. 按值传递与拷贝省略

1.1 按值传递的概念

在 C++ 中,按值传递意味着函数参数是通过创建实参对象的副本来传递的。通常会触发拷贝构造或移动构造函数。按值传递可以在函数内部修改参数副本,而不影响原始实参对象,但这也带来了额外的性能开销。

当我们传递一个对象给函数时,编译器会为这个对象创建一个副本。这个副本的创建需要调用 拷贝构造函数,并且在函数执行结束后,该副本会被销毁,从而调用 析构函数。这一过程涉及到内存的分配与释放,对于大对象而言,可能会导致性能下降。

1.2 示例代码

#include <iostream>
using namespace std;

class A {
public:
    A(int a = 0) : _a1(a) {
        cout << "A(int a) 构造函数被调用, _a = " << _a1 << endl;
    }

    A(const A& aa) : _a1(aa._a1) {
        cout << "A(const A& aa) 拷贝构造函数被调用" << endl;
    }

    A(A&& aa) noexcept : _a1(aa._a1) {
        cout << "A(A&& aa) 移动构造函数被调用" << endl;
    }

    ~A() {
        cout << "~A() 析构函数被调用" << endl;
    }

private:
    int _a1;
};

void f1(A aa) {}  // 按值传递

int main() {
    A aa1(10);  // 创建对象 aa1
    f1(aa1);    // 按值传递,调用拷贝构造
    return 0;
}

1.3 按值传递的性能影响

在上述代码中,按值传递会创建对象的副本,并调用 拷贝构造函数移动构造函数,然后在函数执行结束时,析构函数将会被调用。这一过程虽然实现了副本的安全传递,但对于大型对象,频繁的拷贝和析构会导致性能问题。

1.3.1 完全不优化

在没有任何优化的情况下,按值传递时会创建一个对象的副本,并调用拷贝构造函数。返回对象后,析构函数将被调用两次:一次是为原对象,另一次是为副本。

输出结果

A(int a) 构造函数被调用, _a = 10
A(const A& aa) 拷贝构造函数被调用
~A() 析构函数被调用
~A() 析构函数被调用

解释

  • 对象 aa1 在主函数中通过构造函数被创建。
  • 按值传递时,编译器调用了拷贝构造函数,为 aa1 创建了副本。
  • 当函数 f1 执行结束后,副本被销毁,调用了析构函数。
  • main 函数结束时,原始对象 aa1 也被销毁。
构造对象 aa1
拷贝构造副本传递给 f1
副本执行函数操作
析构副本
主函数结束时析构 aa1

1.4 不同编译器下的优化表现

1.4.1 Visual Studio 2019普通优化

在 Visual Studio 2019 中,编译器在普通优化模式下,依然会调用拷贝构造函数。

输出结果

A(int a) 构造函数被调用, _a = 10
A(const A& aa) 拷贝构造函数被调用
~A() 析构函数被调用
~A() 析构函数被调用

尽管编译器启用了部分优化,但在这种按值传递的情况下,仍然需要调用拷贝构造函数,并最终调用两次析构函数。

1.4.2 Visual Studio 2022激进优化

VS2022 的优化更加激进,它能够跳过对象的拷贝构造,直接传递原始对象的引用。通过内存重用和别名优化,编译器可以避免创建副本。

输出结果

A(int a) 构造函数被调用, _a = 10
~A() 析构函数被调用

解释

  • 在 VS2022 中,拷贝构造函数被优化掉,编译器直接将原对象 aa1 传递给函数 f1说白了,就是编译器上下文分析发现函数里面aa不会修改,那直接就在函数里面使用aa1即可,此时函数里面的aa就是aa1的别名
  • 无需创建副本,也不需要析构副本,只在 main 函数结束时销毁 aa1
构造对象 aa1
直接传递 aa1 到 f1
无拷贝构造, 直接操作
主函数结束时析构 aa1

1.5 小结

  • 按值传递通常会触发拷贝构造或移动构造,并在函数结束时触发析构函数。
  • Visual Studio 2019 中,普通优化仍然会调用拷贝构造函数。
  • Visual Studio 2022 的激进优化则可以跳过拷贝构造,避免副本的创建。

2. 返回值优化(RVO)

2.1 RVO 的概念

返回值优化(RVO) 是编译器的一种优化技术,它允许编译器在函数返回临时对象时,
直接在调用者的内存空间中构造该对象,避免不必要的拷贝或移动构造。

当函数返回一个局部临时对象时,通常会触发一次拷贝构造或移动构造,因为局部对象需要从函数内部复制到外部。然而,RVO 能够避免这种多余的拷贝或移动操作,编译器直接在调用者的内存空间中构造返回的对象-。

2.2 示例代码

A f2() {
    A aa(5);
    return aa;  // 返回局部临时对象
}

int main() {
    A a2 = f2();  // 接收返回值
    return 0;
}

2.3 不同优化下的表现

2.3.1 完全不优化的情况

在没有启用 RVO 的情况下,返回值会经历多次拷贝操作:

  1. f2() 内部创建局部对象 aa
  2. 创建一个临时对象,将 aa 拷贝到这个临时对象中。
  3. 最后将临时对象拷贝给 a2,并调用两次拷贝构造函数。

输出结果

A(int a) 构造函数被调用, _a = 5
A(const A& aa) 拷贝构造函数被调用
A(const A& aa) 拷贝构造函数被调用
~A() 析构函数被调用
~A() 析构函数被调用
~A() 析构函数被调用

解释

  • 局部对象 aaf2 函数内创建,并通过两次拷贝构造传递给 a2
  • 三次析构函数分别销毁局部对象 aa、临时对象和最终返回的 a2
构造局部对象 aa
拷贝到临时对象
将临时对象拷贝给 a2
销毁局部对象 aa
销毁临时对象
销毁 a2
2.3.2 启用 RVO 的情况(Visual Studio 2019)

在 Visual Studio 2019 中,编译器启用了 RVO 优化,避免了创建临时对象,直接将aa拷贝给a2.

输出结果

A(int a) 构造函数被调用, _a = 5
A(const A& aa) 拷贝构造函数被调用
~A() 析构函数被调用
~A() 析构函数被调用

解释

  • 编译器避免了临时对象的创建,但仍通过拷贝构造将 aa 传递给 a2
  • 整个过程调用了一次拷贝构造,并在 a2aa 被销毁时分别调用析构函数。
构造局部对象 aa
将 aa 拷贝到 a2
销毁局部对象 aa
销毁 a2
2.3.3 激进 RVO 的情况(Visual Studio 2022)

Visual Studio 2022 实现了更加激进的 RVO 优化。编译器直接在 a2 的内存空间中构造对象 aa,完全跳过拷贝构造。其实就是下文讲的NRVO

输出结果

A(int a) 构造函数被调用, _a = 5
~A() 析构函数被调用

解释

  • aa 直接在 a2 的内存空间中构造,避免了临时对象和拷贝构造。
  • 最终只需要调用一次析构函数来销毁 a2
直接在 a2 内存空间中构造 aa
销毁 a2

2.4 小结

  • RVO 主要用于返回临时对象的优化,能够在返回局部对象时避免多次拷贝。
  • Visual Studio 2019 中启用了 RVO,减少了临时对象的创建,但仍会调用一次拷贝构造。
  • Visual Studio 2022 则更加激进,完全避免了拷贝构造,直接在返回对象的目标内存空间中构造该对象。

3. 命名返回值优化(NRVO)

3.1 NRVO 的概念

命名返回值优化(NRVO) 是 RVO 的扩展,专门用于优化函数返回命名局部变量的情况。编译器会在调用者的内存空间中直接构造该命名对象,避免临时对象和拷贝操作。

NRVO 允许编译器在返回函数内的命名局部变量时进行优化,直接在目标对象的内存中构造该局部变量,而不是创建一个临时对象进行拷贝或移动。这一优化虽然不像 RVO 那样是 C++ 标准的强制要求,但大多数现代编译器都会尝试实现这种优化

3.2 示例代码

A f3() {
    A a(3);
    return a;  // 返回命名局部变量
}

int main() {
    A a2 = f3();  // 使用返回值
    return 0;
}

在这段代码中,函数 f3 返回命名局部变量 a。没有 NRVO 优化的情况下,a 会首先被拷贝到一个临时对象中,然后该临时对象会被拷贝到 a2

3.3 优化下的不同表现

3.3.1 完全不优化的情况

在没有 NRVO 优化的情况下,返回的命名对象 a 会经历以下拷贝过程:

  1. f3 函数内创建局部对象 a
  2. 创建一个临时对象,将 a 拷贝到这个临时对象中。
  3. 最后将临时对象拷贝到 a2 中。

输出结果

A(int a) 构造函数被调用, _a = 3
A(const A& aa) 拷贝构造函数被调用
A(const A& aa) 拷贝构造函数被调用
~A() 析构函数被调用
~A() 析构函数被调用
~A() 析构函数被调用

解释

  • 局部变量 af3 中创建,并通过两次拷贝构造传递给 a2
  • 由于没有启用 NRVO,因此返回值会触发两次拷贝构造和三次析构函数调用。
3.3.2 启用 NRVO 的情况(Visual Studio 2019 和 2022)

在 Visual Studio 2019 和 Visual Studio 2022 中,NRVO 技术的实现基本一致。局部对象 a 会直接在 a2 的内存空间中构造,没有临时对象和多余的拷贝操作。

输出结果

A(int a) 构造函数被调用, _a = 3
~A() 析构函数被调用

解释

  • 通过 NRVO,编译器直接在 a2 的内存空间中构造局部对象 a,避免了拷贝构造。
  • 整个过程只需要一次析构调用,销毁 a2

3.4 Visual Studio 2022 的优化对比

复杂场景中的 NRVO: Visual Studio 2022 在处理复杂的函数返回场景时,表现更为激进。例如在多层嵌套、条件判断等情况下,NRVO 依然有效,而某些编译器可能在复杂条件下无法实现优化。

以下是一个复杂的 NRVO 示例:

A f4(bool flag) {
    A a1(1);
    A a2(2);
    if (flag) {
        return a1;
    } else {
        return a2;
    }
}

int main() {
    A a

3 = f4(true);  // 使用返回值
    return 0;
}

在这种复杂场景中,Visual Studio 2022 依然能够直接在 a3 的内存空间中构造返回值(无论是 a1 还是 a2),而不会创建临时对象或额外的拷贝构造。并且这种情况下发现只需要返回a1,那甚至可能会跳过a2的创建

输出结果

A(int a) 构造函数被调用, _a = 1
~A() 析构函数被调用

3.5 小结

  • NRVO 针对命名局部变量的优化,能够在返回命名变量时避免临时对象和拷贝构造。
  • Visual Studio 20192022 的 NRVO 实现基本一致,能够在大多数情况下避免拷贝构造。
  • Visual Studio 2022 在处理复杂场景时的 NRVO 优化表现更为激进,即使在条件判断和嵌套场景中,也能有效避免额外的临时对象和拷贝。

4. 赋值操作无法优化的原因

4.1 赋值操作的本质

赋值操作与对象构造不同,它修改已经存在的对象,因此不能像RVO或NRVO那样进行优化。赋值操作必须真正执行对象状态的复制,无法通过跳过拷贝来优化。

在 C++ 中,赋值操作是将一个对象的内容复制到另一个对象中。这与对象的构造不同,因为在赋值操作时,目标对象已经存在,不能通过构造优化来避免对象的状态复制。

4.2 示例代码

A aa1(10);
A aa2(20);
aa1 = aa2;  // 赋值操作

输出结果

A(int a) 构造函数被调用, _a = 10
A(int a) 构造函数被调用, _a = 20
A& operator=(const A& aa) 赋值运算符被调用
~A() 析构函数被调用
~A() 析构函数被调用

解释

  • 对象 aa1aa2 分别通过构造函数创建。
  • 赋值操作需要实际复制 aa2 的数据到 aa1 中,因此必须调用赋值运算符。
构造对象 aa1 和 aa2
调用赋值操作
将 aa2 的内容复制到 aa1
析构 aa2 和 aa1

赋值操作在 C++ 中并没有优化空间,因为在赋值操作时,目标对象已经存在,编译器必须实际执行数据复制的过程,而不能通过拷贝省略来进行优化。


5. Visual Studio 2019 vs Visual Studio 2022 编译器优化差异

5.1 编译器的工作原理

编译器在优化过程中,使用了别名分析内存重用技术。在分析对象的使用模式后,编译器能够判断某些对象的拷贝是多余的,可以直接复用原始对象的内存地址。这种优化策略依赖于编译器对代码中对象生命周期的深层次分析。

5.2 为什么 VS2022 更加激进?

VS2022 能够在更多复杂场景下进行优化,包括跨行优化、多层函数调用等。这是因为编译器能够更好地理解对象的生命周期,并通过对象生命周期分析来跳过冗余的拷贝操作。

例如在以下代码中:

A f4() {
    A a1(1);
    A a2(2);
    return a1;  // 返回局部变量
}

int main() {
    A a3 = f4();
    return 0;
}

VS2019 的输出结果

A(int a) 构造函数被调用, _a = 1
A(int a) 构造函数被调用, _a = 2
A(const A& aa) 拷贝构造函数被调用
~A() 析构函数被调用
~A() 析构函数被调用
~A() 析构函数被调用

在 VS2019 中,即使返回的是局部变量,仍会创建一个临时对象,然后通过拷贝构造将其传递给 a3

VS2022 的输出结果

A(int a) 构造函数被调用, _a = 1
~A() 析构函数被调用

在 VS2022 中,编译器能够更好地分析对象生命周期,跳过了临时对象的创建,直接在 a3 的内存空间中构造返回的局部变量 a1

5.3 编译器的激进优化总结

  • Visual Studio 2019 在大部分情况下能够启用 RVO 和 NRVO,但在某些复杂场景下仍需要额外的拷贝构造。
  • Visual Studio 2022 的优化更加激进,通过更好的对象生命周期分析,能够避免更多不必要的拷贝操作,即使在复杂的函数调用和条件判断中,仍能高效地进行返回值优化。

6. 总结

通过本文,我们深入分析了 C++ 中编译器优化的几个重要方面,包括 返回值优化(RVO)命名返回值优化(NRVO)。这些优化能够显著减少对象的拷贝构造和临时对象的创建,从而提升程序的执行效率。

  • RVO 主要用于优化返回临时对象的场景,Visual Studio 2022 通过激进优化完全跳过了拷贝构造。
  • NRVO 则用于优化返回命名局部变量的场景,Visual Studio 2019 和 2022 的 NRVO 实现基本一致,但 2022 的编译器在复杂场景中的表现更为出色。
  • 在涉及对象赋值的场景中,由于目标对象已经存在,因此无法通过 RVO 或 NRVO 进行优化。

现代编译器已经能够通过 别名分析对象生命周期分析 实现高度智能的优化。程序员不需要显式地进行优化,只需合理设计函数返回结构,编译器会自动帮助完成优化。

如果你希望了解更多编译器优化的底层机制,可以查阅 cppreference RVO文档 和 MSVC优化指南。


以上就是关于C++类与对象深度解析(六):全面剖析拷贝省略、RVO、NRVO优化策略的内容啦,各位大佬有什么问题欢迎在评论区指正,或者私信我也是可以的啦,您的支持是我创作的最大动力!❤️

在这里插入图片描述

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

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

相关文章

828华为云征文|基于华为云Flexus X实例快速搭建Halo博客平台

目录 前言 一、Flexus云服务器X介绍 1.1 Flexus云服务器X实例简介 1.2 Flexus云服务器X实例特点 1.3 Flexus云服务器X实例场景需求 二、Flexus云服务器X购买 2.1 Flexus X实例购买 2.2 购买MySQL加速镜像 2.3 重置密码 2.4 登录服务器 三、Flexus X实例安装Docker 3.1 系统版本…

小小扑克牌算法

1.定义一个扑克牌类Card&#xff1a; package democard; public class Card {public String suit;//表示花色public int rank;//表示牌点数Overridepublic String toString() {return "{"suit rank"}";}//实例方法&#xff0c;初始化牌的点数和花色public…

IBM 撤出背后:国内技术人如何突围?

近年来&#xff0c;随着全球科技行业的风起云涌&#xff0c;各大科技巨头不断调整业务布局&#xff0c;甚至撤出某些市场。近日&#xff0c;IBM宣布在中国市场进一步收缩&#xff0c;引起了业界的广泛关注。作为曾经的科技领军企业&#xff0c;IBM的撤退背后到底传递出什么样的…

Fipexide(FPX):植物组织培养中的新兴化学诱导剂AbMole

在植物科学领域&#xff0c;组织培养技术一直是探索植物发育机制和生物技术应用的强大工具。然而&#xff0c;尽管植物生长调节剂如生长素&#xff08;Auxin&#xff09;和细胞分裂素&#xff08;Cytokinin&#xff09;在促进植物愈伤组织形成和再分化中发挥了关键作用&#xf…

Vue 依赖注入组件通信:provide / inject 使用详解

引言 在 Vue.js 中&#xff0c;我们经常会遇到组件之间需要共享数据的情况。一种常见的解决方案是通过 props 和 $emit 事件来进行数据传递&#xff0c;但对于多层嵌套的组件结构或共享状态的场景&#xff0c;这种方式显得繁琐而不直观。 幸运的是&#xff0c;Vue.js 提供了一…

powerbi -L10-文件夹内的文件名

powerbi -L10-文件夹内的文件名 Folder.Contents letSource Folder.Contents("\\your_folder\ your_folder "),#"Removed Other Columns" Table.SelectColumns(Source,{"Name", "Date modified", "Folder Path"}), in#&q…

国庆头像制作教程,这几种方法轻松制作国庆头像

随着国庆佳节的临近&#xff0c;朋友圈里是不是已经开始弥漫着浓浓的节日气氛&#xff1f;想要让你的头像也加入这场盛宴&#xff0c;成为最吸睛的存在吗&#xff1f;别急&#xff0c;今天就为你揭秘4款超实用的头像制作神器&#xff0c;能够让你的头像显现出浓郁的国庆节气氛&…

Qt 模型视图(二):模型类QAbstractItemModel

文章目录 Qt 模型视图(二)&#xff1a;模型类QAbstractItemModel1.基本概念1.1.模型的基本结构1.2.模型索引1.3.行号和列号1.4.父项1.5.项的角色1.6.总结 Qt 模型视图(二)&#xff1a;模型类QAbstractItemModel ​ 模型/视图结构是一种将数据存储和界面展示分离的编程方法。模…

高性能分布式搜索引擎Elasticsearch详解

♥️作者&#xff1a;小宋1021 &#x1f935;‍♂️个人主页&#xff1a;小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识&#xff0c;和大家一起努力呀&#xff01;&#xff01;&#xff01; &#x1f388;&#x1f388;加油&#xff01; 加油&#xff01…

vue2 + moment 实现日历,并带有上个月和下个月日期的日历

在 Vue 2 中使用 moment 库绘制一个带有上个月和下个月日期的日历&#xff0c;可以通过以下步骤实现。这个日历将显示当前月份的天数&#xff0c;以及前一个月和下一个月的部分日期&#xff08;通常为了让日历对齐为6行&#xff0c;每行7天&#xff09;。 主要步骤&#xff1a…

外国药品位置检测系统源码分享

外国药品位置检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

C语言中值传递

C语言中&#xff0c;值传递的问题 #include <stdio.h> void modifyValue(int x) { x 10; // 修改的是x的副本&#xff0c;对原始数据无影响 printf("在函数中修改的结果是:%d\n",x); }int main() { int a 5; printf("Before: %d\n", a); modifyV…

【资料分析】刷题日记3

第一套 √ 考点&#xff1a;基期比重差很温柔的题 普通专科女生 占比 52.5% - 1.7% 50.8% 成人本专科女生 占比 57.8% - 4.6% 53.2% 相比降低了2.4% 知比重和部分量&#xff0c;求整体在花生老师的解法中体会啥叫适当约分 0.1899 / 47.8% / 87.5% 》0.19 / &#xff08;4…

碎纸片的自动拼接复原技术

摘要&#xff1a;破碎文件的拼接在司法物证复原、历史文献修复以及军事情报获取等领域都有着重要的应用。目前发现对碎纸片的拼接大部分由人工完成&#xff0c;准确率较高&#xff0c;但耗费大量人力财力及时间&#xff0c;效率很低。随着计算机技术的发展&#xff0c;人们试图…

机器人上的DPDK使用思考

引言 项目背景 人形机器人作为智能技术的集大成者&#xff0c;正逐步从科幻电影走进现实生活&#xff0c;广泛应用于工业制造、医疗健康、家庭服务等多个领域。在这一发展过程中&#xff0c;传感器技术的飞速发展和物联网技术的广泛应用&#xff0c;极大地提升了人形机器人对…

微服务实战:规则引擎Drools

1. 概述 * 规则引擎核心思想&#xff1a;将应用程序中的业务决策部分分离出来 * 使得业务规则的变更不需要修改项目代码、重启服务器就可以在线上环境立即生效 2. 执行流程 drools规则引擎由以下三部分构成&#xff1a; Working Memory&#xff08;工作内存&#xff09; Ru…

360手机黑科技“位置穿越”功能修复 360位置穿越使用

​ 360手机刷机 360手机黑科技 360手机位置穿越 360手机位置修复 360手机站&#xff1a;360os.top 资源免费下载: os.360os.top 备用资源站&#xff1a;360手机-360手机刷机RootTwrp 360手机位置穿越 360手机位置穿越‌&#xff0c;是一款虚拟定位软件&#xff0c;无需进行r…

做谷歌外链有什么基础的要求?

做谷歌外链建设时有几个基本的要求需要注意。首先&#xff0c;收录率很关键&#xff0c;只有被谷歌成功收录的外链才会对网站产生正面影响。如果一个外链没有被收录&#xff0c;那它基本上对提升排名没有任何帮助 外链的多样性也是至关重要的。获取来自不同网站和平台的链接能为…

双token无感刷新

文章目录 &#x1f7e2;双token无感刷新1、token过期续期的五种方案对比2、双token的基本概念3、双token无感刷新的原理4、双token无感刷新的实现方式5.前端实现 ✒️总结 &#x1f7e2;双token无感刷新 对于token无感刷新这个东西有复杂度的话&#xff0c;它主要在后端&#x…

网站建设的服务器该如何选择?

服务器的选择对于网站的稳定运行、性能表现以及成本控制至关重要。以下是一些关键的考虑因素&#xff0c;帮助你选择适合的服务器&#xff1a; 明确需求&#xff1a;你需要先明确网站的需求和目标。这包括确定服务器将用于托管什么样的应用&#xff08;如Web前端、应用服务器、…