C++ 编译过程全解析:从源码到可执行文件的蜕变之旅

引言

C++ 作为一种广泛应用于系统开发、游戏编程、嵌入式系统等领域的高级编程语言,其代码需要经过编译才能转换为计算机可执行的机器语言。编译过程涵盖多个复杂阶段,每个阶段对最终生成的可执行文件的性能、稳定性及兼容性都有着深远影响。深入理解 C++ 编译过程,对于开发者优化代码、排查错误、提升程序整体质量至关重要。本文将全面剖析 C++ 编译过程,帮助开发者精准把握其精髓,提升编程实践水平。

一、C++ 编译流程详述

在这里插入图片描述

1.1 预处理阶段

预处理是编译的起始环节,由预处理器负责执行。此阶段主要处理以 # 开头的预处理指令,这些指令犹如给编译器下达的特殊命令,引导编译器对源代码进行初步调整。

  • 头文件包含:当遇到 #include 指令时,预处理器会将指定头文件的全部内容插入到源文件中该指令所在位置。例如,源文件包含 #include <iostream>,预处理器就会把 <iostream> 头文件里关于输入输出流的函数声明、类定义等内容完整地拷贝过来。这一操作使得源文件能够使用头文件中声明的各类函数、变量及类,极大地拓展了代码的复用性与功能性。

  • 宏展开#define 指令用于定义宏,预处理器会把代码中出现的宏标识符替换为对应的宏定义内容。像 #define PI 3.14159,在预处理后,代码里所有的 PI 都会被替换成 3.14159,实现常量值的统一设定,方便代码维护与修改。

  • 条件编译:通过 #ifdef#ifndef#else#endif 等指令,能够依据特定条件决定代码片段是否参与编译。例如,#ifdef DEBUG#endif 之间的代码仅在定义了 DEBUG 宏时才会被编译,这对于在调试阶段输出额外信息、执行特定测试代码极为便利。

  • 注释过滤:预处理器会移除源文件中的所有注释内容,无论是以 // 开头的单行注释,还是位于 /* */ 之间的多行注释,均被剔除。这一操作简化了后续编译步骤的处理,使编译器专注于有效代码分析。

完成上述处理后,预处理器会生成一个通常以 .i.ii 为扩展名的预处理文件,该文件保留了处理后的源代码全貌,为下一阶段编译提供基础输入。

1.2 编译阶段

编译阶段是将预处理后的文件转换为汇编语言的关键过程,编译器在此承担核心转换任务,涵盖多个精细步骤:

  • 词法分析:编译器首先对预处理文件进行词法扫描,依据 C++ 语言的词法规则,将源文件的字符流拆分成一个个基本的单词单元,即记号(Token)。这些记号涵盖关键字(如 ifwhileclass 等)、标识符(变量名、函数名等自定义名称)、常量(数值常量、字符常量、字符串常量)、运算符(+-*/ 等)及界符(;:{} 等)。

  • 语法分析:基于词法分析得到的记号序列,编译器运用语法规则进行分析,构建出对应的语法树。语法树以树形结构呈现代码的语法结构,节点表示语法成分,如表达式、语句、函数定义、类声明等。

  • 语义分析:进一步深入探究代码含义,编译器在此阶段核查变量和函数的使用是否合规、类型是否匹配等语义问题。

  • 代码优化:编译器运用多种优化技术对代码进行转换与精简,旨在提升程序运行效率、减少资源消耗。常见优化技术包括常量折叠、内联函数、公共子表达式消除等。

经过编译阶段的精细处理,编译器最终生成以 .s 为扩展名的汇编代码文件,该文件以汇编语言形式展现源文件逻辑,为进一步转换为机器码做准备。

1.3 汇编阶段

汇编阶段,汇编器担纲主力,将编译器生成的汇编代码转换为机器可直接识别执行的机器码,这一过程是从文本指令迈向二进制指令的关键跨越。

汇编器逐行解析汇编代码,依据特定处理器架构的指令集规范,将每条汇编指令转换为对应的二进制机器码序列。例如,对于常见的 x86 架构,汇编指令 mov eax, 5(将常量 5 传送到寄存器 eax)会被转换为相应的二进制机器码 B8 05 00 00 00(不同指令集机器码格式各异)。

完成转换后,汇编器生成以 .o.obj 为扩展名的目标文件。这些目标文件是二进制格式,包含机器码指令、数据以及符号表、重定位信息等元数据。

1.4 链接阶段

链接阶段作为编译流程的收官环节,链接器负责整合多个目标文件及所需库文件,生成最终能在操作系统上运行的可执行文件。

  • 符号解析与重定位:链接器首先扫描所有输入的目标文件及库文件,构建全局符号表,将各个文件中的符号定义与引用进行匹配关联。对于目标文件中引用但未定义的符号(如调用外部函数或访问其他文件定义的全局变量),链接器在其他文件中查找定义,确定其真实内存地址,并更新目标文件中的引用信息,使程序运行时能准确跳转至相应地址执行。

  • 段合并与调整:不同目标文件包含代码段(存放可执行指令)、数据段(存储已初始化全局变量、静态变量)、.bss 段(预留未初始化全局变量、静态变量空间)等多个段,链接器将同名段合并,统一编排内存布局,计算各段在最终可执行文件中的偏移地址,确保程序加载运行时内存分配合理有序。

链接过程依据库文件使用方式分为静态链接与动态链接:

  • 静态链接:链接时,将所需库文件中的代码与数据完整拷贝至可执行文件,生成独立、自包含的可执行程序。优点是运行时无需额外依赖库文件,执行效率高,启动速度快;缺点是导致可执行文件体积庞大,若多个程序使用相同库,会造成内存中库代码冗余存储,资源浪费,且库更新时需重新编译所有关联程序。

  • 动态链接:编译时仅在可执行文件中记录所需动态库的名称、符号等信息,程序运行时,操作系统加载器依据这些信息动态加载共享的动态链接库到内存,并完成符号解析与重定位。优势在于多个程序可共享同一动态库,节省内存;动态库更新时,无需重新编译程序,便于维护升级;缺点是程序启动时需额外时间加载动态库,运行过程中若动态库缺失或版本不兼容易引发错误,且存在一定安全风险,如动态库路径被篡改可能导致恶意代码注入。
    在这里插入图片描述

二、C++ 编译优化策略

2.1 编译时优化

编译时优化由编译器在编译阶段自动执行,旨在减少运行时计算开销、提升程序执行效率,诸多实用技术广泛应用于现代编译器中。

  • 常量折叠:编译器对编译期能确定结果的常量表达式提前求值,将表达式替换为常量值。例如,const int a = 5 + 3;,编译器直接将 a 赋值为 8,后续代码使用 a 处直接用 8 替代,避免运行时重复加法运算。

  • 内联函数:针对短小、频繁调用的函数,编译器将函数体嵌入调用点,减少函数调用开销。像 inline int add(int x, int y) { return x + y; },在调用 add 函数处,编译器直接替换为 x + y 计算代码,省却函数调用的参数传递、栈帧创建销毁等额外开销,加速程序执行。

  • 模板优化:模板代码在编译时依据具体类型实例化生成特定代码,编译器借此施展更多优化手段。以通用排序函数模板为例,template<typename T> void sort(T arr[], int size);,当用于 int 型数组排序时,编译器生成适配 int 类型的排序代码,针对 int 数据特性(如固定大小、内存对齐等)优化,比通用代码更高效。

2.2 循环优化

循环作为程序频繁出现的结构,其优化对性能提升意义重大,编译器与开发者可从多维度实施优化策略。

  • 循环展开:通过将循环体重复展开,减少循环控制语句执行次数,提升指令级并行度。例如,for (int i = 0; i < 100; i++) { do_something(i); },若展开为 for (int i = 0; i < 100; i += 4) { do_something(i); do_something(i + 1); do_something(i + 2); do_something(i + 3); },循环控制指令(如比较、递增操作)从 100 次降为 25 次,每次迭代能执行更多有效操作。

  • 循环不变代码外提:把循环中不依赖循环变量、每次迭代结果相同的代码移至循环外,避免重复计算。如 for (int i = 0; i < 100; i++) { int a = 5 * 2; do_something(a, i); },可优化为 int a = 5 * 2; for (int i = 0; i < 100; i++) { do_something(a, i); },提前计算 a 值,降低计算成本。

2.3 内存访问优化

内存访问速度常是程序性能瓶颈,优化内存访问能充分挖掘硬件性能,提升程序整体效率。

  • 数据局部性优化:分空间与时间局部性,前者指程序倾向访问临近内存位置数据,后者指近期访问数据短期内可能再次访问。利用此特性,合理组织数据结构与算法可提升缓存命中率。如多维数组遍历,按行优先(C、C++ 默认)比列优先更契合缓存读取顺序,因连续内存存放同行元素。

  • 内存管理优化:高效的内存分配与回收是关键。避免频繁小块内存动态分配(如在循环内),以减少内存碎片化与分配开销,必要时提前一次性分配大块内存,按需分割使用;对不再使用内存及时释放,防止内存泄漏累积拖慢程序。

2.4 并行化与向量化

随着硬件多核、SIMD 技术发展,利用并行与向量化提升性能成重要方向,适配编译器与编程库为开发者赋能。

  • 并行化:借助多核心处理器并行执行特性,将任务拆分至多个线程或进程同步运行,加速计算。如使用 OpenMP 库,在循环前添加 #pragma omp parallel for 指令,编译器自动将循环迭代分配至多核心。

  • 向量化:编译器将数据按特定宽度(如 128 位、256 位)拆分为向量,运用 SIMD 指令集并行处理,单指令操作多数据元素,提升计算效率。现代处理器 SSE、AVX 指令集广泛支持向量化,对数组运算、图像处理等数据密集型任务效果卓越。

三、跨平台编译挑战与应对

3.1 跨平台开发问题剖析

跨平台开发面临诸多棘手难题,根源在于不同平台在硬件架构、系统特性及编译器支持等多方面存在显著差异。

  • 硬件架构差异:不同平台处理器指令集架构大相径庭,如常见的 x86x86_64ARMMIPS 等架构,各自指令集功能、格式与编码规则截然不同。ARM 架构常用于移动设备与嵌入式系统,注重能耗与性能平衡,指令集精简高效;x86_64 广泛应用于桌面与服务器领域,指令集丰富强大,能处理复杂运算任务。

  • 系统特性差异

    • 内存管理:不同操作系统内存管理机制差异明显。Windows 系统内存分配粒度、内存布局与 Linux 系统存在差别,Windows 内存分配函数(如 HeapAlloc)与 Linux 的 malloc 在底层实现、分配策略上各有侧重。

    • 文件系统:文件路径表示上,Windows 惯用反斜杠 \,如 C:\Program Files\,而 Linux、macOS 等类 Unix 系统统一使用正斜杠 /,如 /usr/local/;文件属性、权限管理同样差异显著。

  • 编译器差异:主流编译器如 GCC(GNU Compiler Collection)、Clang、Visual C++ 对 C++ 标准支持程度参差不齐。部分新 C++ 特性,如 C++17 的结构化绑定、C++20 的模块特性,在老旧编译器版本中可能未完整实现,导致使用新特性代码无法编译。

3.2 应对策略探讨

为攻克跨平台编译难关,一系列行之有效的策略应运而生,从构建系统选型到代码架构设计,全方位助力开发者跨越平台鸿沟。

  • 使用跨平台构建系统

    • CMake:作为广泛应用的跨平台构建系统,它运用简洁且平台无关的 CMakeLists.txt 文件描述项目构建逻辑。开发者指定源文件、头文件路径、依赖库等信息,CMake 依据目标平台(Windows、Linux、macOS 等)自动生成对应平台原生构建脚本。

    • Meson:新兴的现代跨平台构建系统,采用简洁的 Meson.build 文件定义项目。凭借简洁语法与高效构建性能,快速分析项目依赖,生成优化构建指令,且与多种编译器无缝配合,支持增量构建、交叉编译等高级特性。

  • 遵循 C++ 标准:坚守 C++ 标准库与核心语言特性是基石,尽量规避特定平台扩展或非标准特性。利用 CppCheckClang-Tidy 等静态分析工具检查代码规范性,确保代码严格遵循标准,增强可移植性。

  • 抽象平台相关代码:运用分层架构设计理念,将平台特定代码封装于底层独立模块。如文件操作、网络通信、图形界面交互等功能,通过抽象基类或接口定义统一调用方式,在底层针对不同平台(Windows API、Linux 系统调用、macOS 框架)实现具体细节,上层业务逻辑仅依赖抽象层,移植时只需更替底层实现,核心逻辑不受波及。

  • 使用跨平台库

    • Qt:功能强大的跨平台 GUI(Graphical User Interface)框架,提供统一 API 涵盖窗口管理、控件绘制、事件处理等功能,代码一次编写,无需修改即可在 Windows、macOS、Linux 等多平台生成原生界面风格应用。

    • Boost:涵盖多领域的 C++ 库集合,如 Boost.Filesystem 提供统一文件操作接口,Boost.Thread 实现跨平台多线程支持,借助这些成熟库组件,避免重复造轮,巧妙规避平台底层差异陷阱。

  • 处理编译器差异:优先选用兼容性强、对 C++ 标准支持完备的编译器作为基准,如 GCC 在跨平台开发中应用广泛。针对特定平台需使用本地编译器时,借助条件编译指令(#ifdef#ifndef 等)或预处理宏,依据编译器标识选择性包含适配代码片段,确保代码在不同编译器顺利编译,行为一致。

  • 管理依赖库:跨平台开发中,精心挑选依赖库至关重要。优先考量支持多平台且维护活跃的库,如 SQLite 数据库库,具备良好跨平台特性与稳定性。借助 vcpkgConan 等跨平台库管理工具,统一依赖库安装、版本控制与链接配置流程,自动适配不同平台,降低手动管理复杂度。

四、模板元编程与泛型编程的编译处理

4.1 模板实例化机制

在 C++ 编译过程中,模板实例化是关键环节。当编译器遇到模板定义时,并不会直接生成代码,而是在模板被使用时,依据传入的具体类型参数进行实例化。以函数模板为例,如 template<typename T> T add(T a, T b) { return a + b; },当在代码中调用 add(5, 3) 时,编译器基于实参 53 的类型 int,推导出模板参数 Tint,进而生成针对 int 类型的函数代码,实现 int 型数据相加逻辑。

4.2 名称修饰与模板特化

C++ 引入诸多高级特性,如函数重载、模板等,致使同名函数或模板实例大量涌现。为区分这些同名实体,编译器采用名称修饰策略。在编译时,函数名依据其参数类型、个数、是否为常量引用等特征被编码修饰。例如,对于普通函数 int add(int a, int b) 与重载版本 double add(double a, double b),编译器可能将它们分别修饰为类似 _add_int_int_add_double_double 的内部名称,存入符号表。

模板特化与重载则进一步拓展编译期多态性。模板特化允许针对特定类型定制模板实现,分为完全特化与偏特化。完全特化如 template<> class Vector<bool> { // 针对bool型的特化实现 };,专为 bool 类型设计优化存储结构(可能采用位域节省空间)与操作逻辑,提升性能。偏特化如 template<typename T> class Vector<T*> { // 针对指针类型的偏特化实现 };,针对指针类型共性提供统一高效处理方式。

4.3 模板元编程特性

模板元编程赋予 C++ 编译期强大 “编程” 能力,其中递归模板、SFINAE(Substitution Failure Is Not An Error)与 Concepts 是核心特性。

递归模板常用于实现编译期计算,以计算阶乘为例,template<int N> struct Factorial { static const int value = N * Factorial<N - 1>::value; }; template<> struct Factorial<0> { static const int value = 1; };,通过模板实例化递归展开,在编译期算出阶乘值,供后续代码使用,避免运行时重复计算开销,提升效率。

SFINAE 是模板匹配关键规则,当模板实参替换失败时,编译器不会报错,而是尝试其他重载决议。如 template<typename T> typename T::value_type get_value(T t); template<typename T> T get_value(T t);,对 int 型变量调用 get_value,第一个模板因 intvalue_type 成员替换失败,编译器依 SFINAE 规则选用第二个模板,保障编译顺利推进。

C++20 引入的 Concepts 为模板参数约束带来革新,增强代码可读性与错误提示。例如,定义 template<typename T> concept Integral = std::is_integral_v<T>;,后续模板可使用 Integral<T> 约束参数必须为整型,如 template<Integral T> void process(T t);,使代码意图清晰,编译器能更早发现类型不符错误,优化模板编程体验。

4.4 编译模型与代码膨胀

C++ 编译模型涵盖包含编译模型与分别编译模型,二者在处理模板代码时各有千秋。包含编译模型,源文件直接 #include 模板定义,编译器每次使用模板均重新编译,虽简单直接,但在大型项目中,若多处使用同一模板,重复编译易引发代码膨胀,增加编译时间与二进制文件体积。

分别编译模型则试图缓解此问题,模板定义与声明分离,源文件仅包含声明,模板实例化延迟至链接阶段。如在头文件声明 template<typename T> class Matrix;,源文件实现 template<typename T> class Matrix { // 具体实现 };,使用处 Matrix<int> m;,编译器前期仅记录模板依赖,链接时统一实例化。但此模型增加链接复杂性,若模板实现变更,依赖它的文件需重新链接,且同样可能因不当使用引发代码膨胀。

五、结语

C++ 编译过程是一个复杂但至关重要的过程,从预处理、编译、汇编到链接,每个阶段都对最终的可执行文件产生深远影响。通过理解编译过程的每个环节,开发者可以更好地优化代码、排查错误,并提升程序的整体性能。希望本文的解析能够帮助开发者更深入地理解 C++ 编译过程,并在实际项目中应用这些知识,提升编程水平。

参考文献

  1. Adam优化器
  2. L2正则化
  3. 数据增强技术

未觉池塘春草梦,阶前梧叶已秋声。

在这里插入图片描述
学习是通往智慧高峰的阶梯,努力是成功的基石。
我在求知路上不懈探索,将点滴感悟与收获都记在博客里。
要是我的博客能触动您,盼您 点个赞、留个言,再关注一下。
您的支持是我前进的动力,愿您的点赞为您带来好运,愿您生活常暖、快乐常伴!
希望您常来看看,我是 秋声,与您一同成长。
秋声敬上,期待再会!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据库的概念和操作

目录 1、数据库的概念和操作 1.1 物理数据库 1. SQL SERVER 2014的三种文件类型 2. 数据库文件组 1.2 逻辑数据库 2、数据库的操作 2.1 T-SQL的语法格式 2.2 创建数据库 2.3 修改数据库 2.4 删除数据库 3、数据库的附加和分离 1、数据库的概念和操作 1.1 物理数据库…

【CSS in Depth 2 精译_096】16.4:CSS 中的三维变换 + 16.5:本章小结

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第五部分 添加动效 ✔️【第 16 章 变换】 ✔️ 16.1 旋转、平移、缩放与倾斜 16.1.1 变换原点的更改16.1.2 多重变换的设置16.1.3 单个变换属性的设置 16.2 变换在动效中的应用 16.2.1 放大图标&am…

期权懂|个股期权的流动性如何?

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 个股期权的流动性如何&#xff1f; 个股期权作为场外交易工具&#xff0c;具有较高的灵活性。场外交易意味着交易双方可以直接协商交易条款&#xff0c;这有助于满足不同投资者的…

关于在M系列的Mac中使用SoftEtherClient软件

1. 前言 本文说明的是在M系列的苹果的MacBook中如何使用SoftetherClient这款软件&#xff0c;是直接在MacOS操作系统中安装连接使用&#xff0c;不是在PD环境或者非ARM架构的Mac中安装使用。 PS&#xff1a;别费劲百度了&#xff0c;很少有相关解决方案的&#xff0c;在国内会…

linux自动化批量分发SSH密钥同时批量测试SSH连接教程(包含自动化脚本代码)

1、检查端口 检查分发对象22端口是否打开 nmap -p22 ip地址如果要批量检查端口可以参考我写的这篇文章&#xff1a;linux自动化一键批量检查主机端口 2、命令行分发密钥原理 Linux分发密钥原理主要涉及SSH&#xff08;Secure Shell&#xff09;协议&#xff0c;该协议用于…

vue3学习笔记(9)-pinia、storeToRefs、getters

1.新的集中式状态&#xff08;数据&#xff09;管理库&#xff0c;redux vuex pinia 搭建 2.ref拆包 如果在reactive里面定义ref&#xff0c;则打印c时&#xff0c;无需.value 他自动拆包&#xff0c;如果直接在外面定义的ref则需要.value,他没有拆包 3.pinia存储读取数据 存…

Oracle 11G还有新BUG?ORACLE 表空间迷案!

前段时间遇到一个奇葩的问题&#xff0c;在开了SR和oracle support追踪两周以后才算是有了不算完美的结果&#xff0c;在这里整理出来给大家分享。 1.问题描述 12/13我司某基地MES全厂停线&#xff0c;系统卡死不可用&#xff0c;通知到我排查&#xff0c;查看alert log看到是…

深度学习:基于MindSpore NLP的数据并行训练

什么是数据并行&#xff1f; 数据并行&#xff08;Data Parallelism, DP&#xff09;的核心思想是将大规模的数据集分割成若干个较小的数据子集&#xff0c;并将这些子集分配到不同的 NPU 计算节点上&#xff0c;每个节点运行相同的模型副本&#xff0c;但处理不同的数据子集。…

机器学习-高斯混合模型

文章目录 高斯混合模型对无标签的数据集&#xff1a;使用高斯混合模型进行聚类对有标签的数据集&#xff1a;使用高斯混合模型进行分类总结实战 高斯混合模型 对无标签的数据集&#xff1a;使用高斯混合模型进行聚类 对有标签的数据集&#xff1a;使用高斯混合模型进行分类 总结…

android studio android sdk下载地址

android studio安装后&#xff0c;因为公司网络原因&#xff0c;一直无法安装android sdk 后经过手机网络&#xff0c;安装android sdk成功如下&#xff0c;也可以手动下载后指定android sdk本地目录 https://dl.google.com/android/repository/source-35_r01.zip https://dl…

【RK3588 Linux 5.x 内核编程】-内核I2C子系统介绍

内核I2C子系统介绍 文章目录 内核I2C子系统介绍1、内核中的I2C子系统2、内核中的I2C驱动2.1 获取I2C适合器2.2 创建i2c_board_info与设备2.3 创建设备ID和I2C驱动2.4 数据传输2.4.1 发送数据2.4.2 读取数据3、I2C总线如何工作I2C 是一种用于双线接口的串行协议,用于连接低速设…

更新本地项目到最新git版本脚本

由于平时工作中项目较多&#xff0c;每天刚上班都需要更新一下项目代码&#xff0c;一个一个更新感觉稍微麻烦了一些&#xff0c;所以写了一个简单的shell脚本&#xff0c;每天到公司先执行一遍即可。 #!/bin/bash# 进入指定的目录 target_dir"$1"; cd "$targe…

向量检索+大语言模型,免费搭建基于专属知识库的 RAG 智能助手

随着生成式人工智能技术的飞速发展&#xff0c;越来越多的人和企业开始应用AI到日常的工作和生活中。但公域的AI助手其数据来自互联网上的大量公开文本&#xff0c;虽然具有广泛的知识&#xff0c;但在面对一些特定领域的专业问题时&#xff0c;可能会出现回答不够准确或深入的…

python读写文件的三种做法

对于文件操作&#xff0c;python提供了3种做法&#xff1a;open(), os.open() 和with open()语句。 1. open()函数&#xff1a;一般用于更高级的文件读写操作&#xff0c;即人能读懂的用法&#xff0c;如果是写入数据&#xff0c;可用传入字符串。 用法&#xff1a;open(path…

RCE-PLUS (学习记录)

源码 <?php error_reporting(0); highlight_file(__FILE__); function strCheck($cmd) {if(!preg_match("/\;|\&|\\$|\x09|\x26|more|less|head|sort|tail|sed|cut|awk|strings|od|php|ping|flag/i", $cmd)){return($cmd);}else{die("i hate this"…

【分布式文件存储系统Minio】2024.12保姆级教程

文章目录 1.介绍1.分布式文件系统2.基本概念 2.环境搭建1.访问网址2.账号密码都是minioadmin3.创建一个桶4.**Docker安装miniomc突破7天限制**1.拉取镜像2.运行容器3.进行配置1.格式2.具体配置 4.查看桶5.给桶开放权限 3.搭建minio模块1.创建一个oss模块1.在sun-common下创建2.…

目标检测入门指南:从原理到实践

目录 1. 数据准备与预处理 2. 模型架构设计 2.1 特征提取网络原理 2.2 区域提议网络(RPN)原理 2.3 特征金字塔网络(FPN)原理 2.4 边界框回归原理 2.5 非极大值抑制(NMS)原理 2.6 多尺度训练与测试原理 2.7 损失函数设计原理 3. 损失函数设计 4. 训练策略优化 5. 后…

react中实现拖拽排序

效果图&#xff1a;如下 效果说明&#xff1a; 1. 点击“选择”按钮&#xff0c;打开弹窗 2. 左侧数据是调接口回显来的 3. 点击左侧某条数据&#xff0c;这条被点击的数据就会被添加到右侧 4. 右侧的数据可以上下拖动换位置 5. 右侧有数据时&#xff0c;点击"确定"…

亚马逊国际站商品爬虫:Python实战指南

在数字化时代&#xff0c;数据的价值不言而喻。对于电商领域而言&#xff0c;获取竞争对手的商品信息、价格、评价等数据&#xff0c;对于市场分析和策略制定至关重要。本文将带你了解如何使用Python编写爬虫&#xff0c;以亚马逊国际站为例&#xff0c;按照关键字搜索并获取商…

Problem: 3046. 分割数组(LeetCode)

题目来源&#xff1a; https://leetcode.cn/problems/split-the-array/description/3046. 分割数组 - 给你一个长度为 偶数 的整数数组 nums 。你需要将这个数组分割成 nums1 和 nums2 两部分&#xff0c;要求&#xff1a; * nums1.length nums2.length nums.length / 2 。 *…