当前位置: 首页 > news >正文

C++ 的 if-constexpr

1 if-constexpr 语法

1.1 基本语法

​ if-constexpr 语法是 C++ 17 引入的新语法特性,也被称为常量 if 表达式或静态 if(static if)。引入这个语言特性的目的是将 C++ 在编译期计算和求值的能力进一步扩展,更方便地实现编译期的分支选择动作。早期的 C++ 缺少类似的语言特性,C++ 开发者不得不使用 tag dispatching 这样的惯用手法或者借助于模板特化机制让编译器在模板参数推导时“曲折地”实现一些静态选择。C++ 11 标准明确了 SFINAE 机制的应用,并提供了 enable_if ,二者配合可以更方便地实现编译期的分支选择,但是与 if-constexpr 相比,可读性和易用性都差了几条街。

​ 在介绍 if-constexpr 的“神通”之前,前来看一下 if-constexpr 的语法形式。其实我们在介绍如何让自己的设计的类型支持结构化绑定的时候(《让自定义类型支持结构化绑定》),为实现 get<N>() 成员方法,就用到了这种语法,这里再回顾一下 if-constexpr 语法的表达形式:

struct FooTest
{template<std::size_t N>const auto& get() const{if constexpr (N == 0) return name;else if constexpr (N == 1) return age;  //else if 分支中的 constexpr 说明符可以省略else return weight;}
};

这个函数中对模板参数 N 的判断在编译期间进行,由哪个分支返回数据也是在编译期间就决定了,false 分支中的代码甚至不会出现在实例化后的函数代码中。以get<N>()成员函数为例,如果使用 FooTest 的代码用到 get<0>() 取 name 这个成员,则最终实例化后会得get<0>()的特化实现:

struct FooTest
{template<>const std::string& get<0>() const{return name;}
};

如果代码中还用了get<1>()取 age 的值,则编译器还会实例化出 get<1>()这个特化版本:

template<>
const int& get<1>() const
{return age;
}

1.2 扩展说明

1.2.1 条件表达式

​ 常量 if 表达式中的条件表达式必须是 bool 类型的常量表达式,或者是可转换成 bool 类型的常量表达式。因为这个条件表达式是在编译期进行评估的,所以 constexpr 修饰的常量或函数都可以出现在这个表达式中,但是运行期间的变量或非 constexpr 的函数不可以出现在条件表达式中。

​ C++ 17 中,lambda 表达式(lambda 函数)可以被显式声明为 constexpr,但是当一个 lambda 表达式和相关的上下文一起达成一个闭包时,如果这个闭包在一个 constexpr 上下文中使用,即使没有将其显式声明为 constexpr,它也会被当作 constexpr 使用,比如:

auto DoubleIt = [](int n)  {  return n + n;  };
template<std::size_t N>
bool Func2()
{if constexpr (DoubleIt(N) < 100)return true;elsereturn false;
}std::cout << Func2<10>() << ", " << Func2<50>() << std::endl;  //1, 0

1.2.2 false 分支处理

​ 函数模板实例化时,评估为 false 分支的语句不会出现在最终实例化后的函数代码中,但是编译器会对其进行语法检查,当出现语法错误时也会报错(有些编译器报错)。虽然会进行语法检查,但是 false 分支中的 return 语句不会参与函数的返回值类型推定,比如这个例子:

template<typename T>
auto get_value(T t)
{if constexpr (std::is_pointer_v<T>)return *t; elsereturn t; 
}

std::is_pointer_v<T>为 true 时,else 分支中的 return t 语句不参与返回值类型推定,函数返回值类型推定为 *t 的类型。当std::is_pointer_v<T>为 false 时正好相反,else 分支中的 return t 语句将决定返回值类型,函数返回值类型推定为 t 的类型。这里需要注意,如果取消配合 if-constexpr 的 else 分支,改用函数设计常用的默认返回方式,编译器就会报错,比如:

template<typename T>
auto get_value(T t)
{if constexpr (std::is_pointer_v<T>)return *t; return t; 
}

这个 get_value2() 函数的代码语义与前面的 get_value() 函数一样,但是编译器会报错,因为最后的 return 语句也参与返回值类型的推定,并且当 T 是指针类型的时候,两个 return 语句的返回值类型推定会互相矛盾。

​ 尽管编译器会对 false 分支的代码进行语法检查,但是 false 分支的代码会被丢弃,所以不参与代码链接。比如这个例子:

extern int x; //int f()
{if constexpr (true)return 0;else if (x)return x;elsereturn -x;
}f(); //调用 f

尽管全局变量 x 只有一个 extern 声明,并没有定义,但是这段代码编译正常,没有错误。因为 else if 和 else 分支的代码都被丢弃,编译器没有为链接代码而定位 x 的需要。

​ 编译器之所以要对准备丢弃的 false 分支代码进行语法检查,可能原因是它要对整个 if 语句进行分析,了解每个分支逻辑的起始位置和结束位置,以便能够正确地保留 true 分支的代码,丢弃 false 分支的代码。

1.2.3 初始化语句

​ C++ 17 开始支持在 if 语句中使用初始化语句,当然,if-constexpr 语法上也支持初始化语句,只是要求初始化语句也只能使用常量和常量表达式。比如这个例子中的 k 的初始化:

template<std::size_t N>
bool Func()
{if constexpr (constexpr std::size_t k = 3; (N % k) == 0)return true;elsereturn false;
}

k 必须是个常量,初始化 k 的表达式必须是常量表达式。

2 if-constexpr 的作用

​ 可在编译期执行的 if-constexpr,用于模板元编程中的条件判断,不仅扩展了模板元编程的分支处理能力,也简化了很多以前用非常复杂方式实现的分支判断代码,使得模板元编程对条件分支的处理代码更直观,更容易理解。这一部分我们用三个例子,分别介绍一下 if-constexpr 的作用,包括对传统的 tag dispatching 和模板特化习惯用法的比较。

2.1 简化可变参数的处理方式

​ 使用 if-constexpr 可以提高泛型代码的可读性,上一节介绍的 get<N>() 的函数,如果不用 if-constexpr,就需要借助于模板的递归推导来解决 N 的个数不确定问题。具体做法就是定义一个泛化版本加上一个特化版本,这样实现起来不仅麻烦,代码可读性也大打折扣。这一节,我们用一个之前介绍过的用于求和的函数模板为例,介绍一下 if-constexpr 对可变参数的处理以及提高代码可读性能带来的好处。

​ 在 C++ 17 之前,没有折叠表达式和 if-constexpr,对参数包的处理需要用到模板的递归推导,需要定义一个结束递归推导的特化实例,非常不直观:

template<typename T>
auto Sum(T arg)
{return arg;
}template<typename T, typename... Args>
auto Sum(T arg, Args... args_left)
{return arg + Sum(args_left...);
}std::cout << Sum(3, 5, 8) << std::endl;  //输出16
std::cout << Sum(std::string("Emma "), std::string(" love cats!")) << std::endl; //输出 Emma love cats!

C++ 17 引入了折叠表达式,用了折叠表达式就简单多了,看看折叠表达式的版本:

template<typename... Args>
auto Sum(Args&&... args)
{return (0 + ... + args);
}

但是折叠表达式的语法让很多初学者“毛骨悚然”,如果改成用 if-constexpr 实现,则代码更符合直觉,可读性也上了一个台阶:

template <typename T, typename... Args>
auto Sum(T arg, Args... args)
{if constexpr (0 == sizeof...(Args))return arg;elsereturn arg + Sum(args...);
}

2.2 比std::enable_if 更灵活

​ SFINAE (Substitution Failure Is Not An Error)的意思就是模板推导的过程中,如果模板参数替换后得到一个无意义的错误结果,编译器并不立即报错,而是暂时忽略这个模板函数声明,继续参数推导和替换。C++ 11 引入的 std::enable_if 就是实现 SFINAE 的最直接方式,下面用 ToString() 函数为例(注意,这不是一个严谨的实现,只是作为一个例子),看看如何用 std::enable_if 实现编译期的条件分支。

//也可以用 enable_if_t
template<typename T>
std::enable_if<std::is_arithmetic<T>::value, std::string>::type
ToString(T t)
{return std::to_string(t);
}template<typename T>
std::enable_if<!std::is_arithmetic<T>::value, std::string>::type
ToString(T t)
{return t;
}

std::to_string() 支持将一个整数型数据或浮点数型数据转成字符串,如果 T 本身就是 std::string 类型,则不需要转换。std::enable_if 的作用就是通过对返回值类型的控制,使得当类型 T 与函数代码不匹配(比如 to_string() 函数不支持 std::string 类型)的时候产生一个错误的函数声明。举个例子,当 T 是 std::string 类型时(不是数字类型),编译器对两个模板函数进行参数替换后得到两个函数声明:

template<>
ToString<std::string>(std::string t);template<>
std::string ToString<std::string>(std::string t);

第一个替换结果没有函数返回值,是个语法上错误的函数声明,编译器会丢弃这个替换结果,选择第二个语法上正确的作为最终的 ToString() 函数重载裁决结果。如此一来,就通过 std::enable_if 与 SFINAE 机制配合,实现了编译期分支选择的目的。

​ 但是使用 std::enable_if 控制需要注意一点,std::enable_if 只能将条件分割成两种情况,就是两个条件必须互斥,即一个是 true 条件,另一个必须是 false 条件,否则一旦出现两个判断条件都是 true 的情况,就会出现两个正确的结果,导致编译器报告“模棱两可的函数调用” 的编译错误。通过上面的例子可以看出,尽管 std::enable_if 也能实现编译期的条件分支选择,但是代码并不直观,约束条件比较多,且只能实现两个分支的选择。现在看看使用 if-constexpr 的实现方案:

template<typename T>
auto ToString(T t)
{if constexpr (std::is_arithmetic<T>::value)return std::to_string(t);elsereturn t;
}

这样的代码要比写两个重载函数让编译器按照 SFINAE 原则匹配调用的方式更直观,也更容易理解和维护。

2.3 比 tag dispatching 更直观

​ tag 就是一些没有数据,没有操作的空类型,它们可以作为函数参数来影响编译器对重载函数的选择。用 tag dispatching 技术首先要定义 tag,根据本文的例子,我们定义两个 tag:

struct NumTag {};
struct StrTag {};

接着要定义重载函数,唯一不同的参数就是 tag 类型,tag 类型作为函数的哑形参只影响编译器对重载函数的选择,最终这个没有的参数都会被编译器优化掉:

template <typename T>
auto ToString_impl(T t, NumTag)
{return std::to_string(t);
}template <typename T>
auto ToString_impl(T t, StrTag)
{return t;
}

最后就是实现 ToString(),根据 T 的类型确定是调用 ToString_impl(t, NumTag()); 还是调用 ToString_impl(t, StrTag());,具体做起来就八仙过海,各显神通,比如这个使用自定义 type_traits 的方式:

template <typename T> //一个并不严谨的泛化版本
struct traits
{typedef NumTag tag;
};template <>   //针对 std::string 的特化版本
struct traits<std::string>
{typedef StrTag tag;
};template <typename T>
auto ToString(T t)
{return ToString_impl(t, typename traits<T>::tag());  //根据 traits<T>::tag 选择 ToString_impl()
}

​ 对比上一节用 if constexpr 实现的版本,可以看出来使用 tag dispatching 的代码比较晦涩,需要研究一下 tag 的定义才能了解分支选择的具体条件,代码实现不如 if constexpr 直观。

3 if-constexpr 与 if 的区别

3.1 if 为什么不行

​ 上一节的 ToString() 函数的例子如果不用 if-constexpr,像这样直接用 if 实现:

template<typename T>
auto ToString(T t)
{if (std::is_arithmetic<T>::value)return std::to_string(t);elsereturn t;
}

是否也可以呢?答案是不可以,因为 std::is_arithmetic<T> 是在编译期求值的,当代码中需要将整数 42 转成字符串,调用 ToString(42) 的时候,传入参数是 int 或 double,评估结果是 true,此时函数模板被实例化成:

auto ToString(int t)
{if (true)return std::to_string(t);elsereturn t;
}

这个实例化结果是无法编译的,因为返回值到底是整数还是 std::string 呢?两个 return 语句的返回值类型不一致。再看看到传入参数是 std::string 的情况,此时 if 的评估结果是 false,函数模板被实例化成:

auto ToString(std::string t)
{if (false)return std::to_string(t);elsereturn t;
}

尽管走 else 分支,直接返回 t 没有问题,但是 if 分支的编译会有问题,因为 std::to_string() 不支持 std::string 类型。所以,直接使用 if 语句是不可以的。

3.2 if-constexpr 为什么可以

​ 现在对比使用 if-constexpr 的情况。前面提到过,对于 false 分支编译只进行语法分析,不生成代码。所以当代码中出现 ToString(42) 的调用的时候,传入参数是 int,评估结果是 true,此时函数模板被实例化成:

std::string ToString(int t)
{return std::to_string(t);
}

当传入参数是字符串类型的时候,else 分支就成为 true 分支被保留,函数模板实例化的结果就是:

std::string ToString(std::string t)
{return t;
}

最终实例化的结果和使用 std::enable_if 的结果是一样的,但是语法比 std::enable_if 简单,直观。

4 if-constexpr 与 #if 的区别

​ 编译期 if 表达式很容易让人想到 C++ 的条件编译指令 #if,但是它们的区别还是很明显的,主要有三点:

  • 处理阶段不同:#if 条件编译指令是在代码预处理阶段解析的,预处理器处理完成后提交给编译器时,编译器只能看到 true 分支的内容,而 if-constexpr 的代码都是在编译阶段进行处理的;
  • 条件表达式要求不同:首先是代码处理的阶段不一样,#if 只能使用用于定义的宏、编译器预定义的宏和环境变量,不能使用代码中的函数或变量,而 if-constexpr 的条件表达式可以是代码中的常量,或者常量函数;
  • false 分支的处理方式不同:条件编译中的 false 分支编译器不进行语法检查,实际上它们在预编译阶段就被过滤掉了,而 if-constexpr 中的 false 分支也进行语法检查。

关注作者的算法专栏
https://blog.csdn.net/orbit/category_10400723.html

关注作者的出版物《算法的乐趣(第二版)》
https://www.ituring.com.cn/book/3180

相关文章:

C++ 的 if-constexpr

1 if-constexpr 语法 1.1 基本语法 ​ if-constexpr 语法是 C 17 引入的新语法特性&#xff0c;也被称为常量 if 表达式或静态 if&#xff08;static if&#xff09;。引入这个语言特性的目的是将 C 在编译期计算和求值的能力进一步扩展&#xff0c;更方便地实现编译期的分支…...

【电气设计】接地/浮地设计

在工作的过程中&#xff0c;遇到了需要测量接地阻抗的情况&#xff0c;组内讨论提到了保护接地和功能接地的相关需求。此文章用来记录这个过程的学习和感悟。 人体触电的原理&#xff1a; 可以看到我们形成了电流回路&#xff0c;导致触电。因此我们需要针对设备做一些保护设计…...

Gone v2 配置管理3:连接 Nacos 配置中心

&#x1f680; 发现 gone-io/gone&#xff1a;一个优雅的 Go 依赖注入框架&#xff01;&#x1f4bb; 它让您的代码更简洁、更易测试。&#x1f50d; 框架轻量却功能强大&#xff0c;完美平衡了灵活性与易用性。⭐ 如果您喜欢这个项目&#xff0c;请给我们点个星&#xff01;&a…...

深度强化学习中的深度神经网络优化策略:挑战与解决方案

I. 引言 深度强化学习&#xff08;Deep Reinforcement Learning&#xff0c;DRL&#xff09;结合了强化学习&#xff08;Reinforcement Learning&#xff0c;RL&#xff09;和深度学习&#xff08;Deep Learning&#xff09;的优点&#xff0c;使得智能体能够在复杂的环境中学…...

浅拷贝与深拷贝

浅拷贝和深拷贝是对象复制中的两种常见方式&#xff0c;它们在处理对象的属性时有本质的区别。 一. 浅拷贝&#xff08;Shallow Copy&#xff09; 浅拷贝是指创建一个新对象&#xff0c;然后将当前对象的非静态字段复制到新对象中。如果字段是值类型的&#xff0c;那么将复制字…...

macOS 安装 Miniconda

macOS 安装 Miniconda 1. Quickstart install instructions2. 执行3. shell 上初始化 conda4. 关闭 终端登录用户名前的 base参考 1. Quickstart install instructions mkdir -p ~/miniconda3 curl https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh -o…...

分布式限流方案:基于 Redis 的令牌桶算法实现

分布式限流方案&#xff1a;基于 Redis 的令牌桶算法实现 前言一、原理介绍&#xff1a;令牌桶算法二、分布式限流的设计思路三、代码实现四、方案优缺点五、 适用场景总结 前言 在分布式场景下&#xff0c;接口限流变得更加复杂。传统的单机限流方式难以满足跨节点的限流需求…...

OpenHarmony子系统开发 - 电池管理(二)

OpenHarmony子系统开发 - 电池管理&#xff08;二&#xff09; 五、充电限流限压定制开发指导 概述 简介 OpenHarmony默认提供了充电限流限压的特性。在对终端设备进行充电时&#xff0c;由于环境影响&#xff0c;可能会导致电池温度过高&#xff0c;因此需要对充电电流或电…...

Cocos Creator版本发布时间线

官网找不到&#xff0c;DeepSeek给的答案&#xff0c;这里做个记录。 Cocos Creator 1.x 系列 发布时间&#xff1a;2016 年 - 2018 年 1.0&#xff08;2016 年 3 月&#xff09;&#xff1a; 首个正式版本&#xff0c;基于 Cocos2d-x 的 2D 游戏开发工具链&#xff0c;集成可…...

修形还是需要再研究一下

最近有不少小伙伴问到修形和蜗杆砂轮的问题&#xff0c;之前虽然研究过一段时间&#xff0c;但是由于时间问题放下了&#xff0c;最近想再捡起来。 之前计算的砂轮齿形是一整段的&#xff0c;但是似乎这种对于有些小伙伴来说不太容易接受&#xff0c;希望按照修形的区域进行分…...

Java面试黄金宝典11

1. 什么是 JMM 内存模型 定义 JMM&#xff08;Java Memory Model&#xff09;即 Java 内存模型&#xff0c;它并非真实的物理内存结构&#xff0c;而是一种抽象的概念。其主要作用是规范 Java 虚拟机与计算机主内存&#xff08;Main Memory&#xff09;之间的交互方式&#x…...

华为p10 plus 鸿蒙2.0降级emui9.1.0.228

需要用到的工具 HiSuite Proxy V3 华为手机助手11.0.0.530_ove或者11.0.0.630_ove应该都可以。 官方的通道已关闭&#xff0c;所以要用代理&#xff0c;127.0.0.1端口7777 https://www.firmfinder.ml/ https://professorjtj.github.io/v2/ https://hisubway.online/articl…...

高速开源镜像站网址列表2503

高速开源镜像站网址列表 以下是国内常用的高速开源镜像站网址列表&#xff0c;涵盖企业和教育机构的主要站点&#xff0c;适用于快速下载开源软件和系统镜像&#xff1a; 一、企业镜像站 阿里云镜像站 地址&#xff1a;https://mirrors.aliyun.com/ 特点&#xff1a;覆盖广泛…...

Python----计算机视觉处理(Opencv:绘制图像轮廓:寻找轮廓,findContours()函数)

一、轮廓 轮廓是图像中目标物体或区域的外部边界线或边界区域&#xff0c;由一系列相连的像素构成封闭形状&#xff0c;代表了物体的基本外形。与边缘不同&#xff0c;轮廓是连续的&#xff0c;而边缘则不一定是连续的。 轮廓与边缘的区别&#xff1a; 轮廓是一组连续的点或线…...

python --face_recognition(人脸识别,检测,特征提取,绘制鼻子,眼睛,嘴巴,眉毛)/活体检测

dlib 安装方法 之前博文 https://blog.csdn.net/weixin_44634704/article/details/141332644 环境: python==3.8 opencv-python==4.11.0.86 face_recognition==1.3.0 dlib==19.24.6人脸检测 import cv2 import face_recognition# 读取人脸图片 img = cv2.imread(r"C:\U…...

【测试工具】如何使用 burp pro 自定义一个拦截器插件

在 Burp Suite 中&#xff0c;你可以使用 Burp Extender 编写自定义拦截器插件&#xff0c;以拦截并修改 HTTP 请求或响应。Burp Suite 支持 Java 和 Python (Jython) 作为扩展开发语言。以下是一个完整的流程&#xff0c;介绍如何创建一个 Burp 插件来拦截请求并进行自定义处理…...

51单片机和STM32 入门分析

51单片机和STM32是嵌入式开发中两种主流的微控制器&#xff0c;它们在架构、性能、应用场景等方面存在显著差异。以下是两者的对比分析及选择建议&#xff1a; 1. 51单片机与STM32的定义与特点 51单片机 定义&#xff1a;基于Intel 8051内核的8位微控制器&#xff0c;结构简单…...

python暴力破解html表单

import requests import time# 目标URL url "http://192.168.3.101/pikachu/vul/burteforce/bf_form.php" # 请替换为实际的目标URL# 已知的用户名 username "admin"# 密码字典文件路径 password_file "passwords.txt"# 伪造请求头&#xff…...

DeepSeek+RAG局域网部署

已经有很多平台集成RAG模式&#xff0c;dify&#xff0c;cherrystudio等&#xff0c;这里通过AI辅助&#xff0c;用DS的API实现一个简单的RAG部署。框架主要技术栈是Chroma,langchain,streamlit&#xff0c;答案流式输出&#xff0c;并且对答案加上索引。支持doc,docx,pdf,txt。…...

流影---开源网络流量分析平台(一)(小白超详细)

目录 流影介绍 一、技术架构与核心技术 二、核心功能与特性 流影部署 流影介绍 一、技术架构与核心技术 模块化引擎设计 流影采用四层模块化架构&#xff1a;流量探针&#xff08;数据采集&#xff09;、网络行为分析引擎&#xff08;特征提取&#xff09;、威胁检测引擎&…...

在IDEA中快速注释所有console.log

在IDEA中快速注释所有console.log 在前端IDEA中&#xff0c;快速注释所有console.log语句可以通过以下步骤实现2&#xff1a; 打开要修改的文件。使用快捷键CtrlF打开搜索框。点击打开使用正则搜索的开关或者通过AltR快捷键来打开。在搜索框输入[]*console.log[]*&#xff0c;…...

python全栈-前端

python全栈-前端 文章目录 HTML标签段落p、换行br、水平线hr图片img路径src超文本链接a超链接之锚点href#id文本有序列表ol无序列表ul自定义列表表格table表格属性单元格合并 表单Forminput标签HTML5新增type属性HTML5新增常用属性 实体字符块元素与行内元素/内联元素容器元素d…...

基于PySide6与pycatia的CATIA绘图文本批量处理工具开发实践

引言 在CAD软件二次开发领域&#xff0c;CATIA的自动化处理一直存在开发门槛高、接口复杂等痛点。本文基于Python生态&#xff0c;结合PySide6 GUI框架与pycatia接口库&#xff0c;实现了一套高效的绘图文本批量处理工具。该工具支持背景视图文本批量处理和交互式文本选择处理…...

Jenkins 集成 SonarQube 代码静态检查使用说明

环境准备 Jenkins 服务器 确保 Jenkins 已安装并运行&#xff08;推荐 LTS 版本&#xff09;。安装插件&#xff1a; SonarQube Scanner for Jenkins&#xff08;用于集成 SonarQube 扫描&#xff09;NodeJS Plugin&#xff08;可选&#xff0c;用于 JavaScript 项目&#xff0…...

pytorch构建线性回归模型

仅仅用于自己记录pytorch学习记录 线性回归模型 &#xff08;1&#xff09;准备数据集 数据&#xff1a;三个数据x[x1,x2,x3] y[y1,y2,y3] import torch #线性回归&#xff0c;我们使用三组数据&#xff0c;分别是&#xff08;1,2&#xff09;&#xff0c;&#xff08;2,4&a…...

本地部署 LangManus

本地部署 LangManus 0. 引言1. 部署 LangManus2. 部署 LangManus Web UI 0. 引言 LangManus 是一个社区驱动的 AI 自动化框架&#xff0c;它建立在开源社区的卓越工作基础之上。我们的目标是将语言模型与专业工具&#xff08;如网络搜索、爬虫和 Python 代码执行&#xff09;相…...

skynet网络包库(lua-netpack.c)的作用解析

目录 网络包库&#xff08;lua-netpack.c&#xff09;的作用解析1. 数据包的分片与重组2. 网络事件处理3. 内存管理4. 数据打包与解包 动态库&#xff08;.so&#xff09;在 Lua 中的使用1. 编译为动态库2. Lua 中加载与调用(1) 加载模块(2) 核心方法(3) 使用示例 3. 注意事项 …...

XXL-Job 二次分片是怎么做的?有什么问题?怎么去优化的?

XXL-JOB二次分片机制及优化策略 二次分片实现原理 XXL-JOB的二次分片是在分片广播策略的基础上&#xff0c;由开发者自行实现的更细粒度数据拆分。核心流程如下&#xff1a; 初次分片&#xff1a;调度中心根据执行器实例数量&#xff08;总分片数n&#xff09;分配分片索引i&…...

零基础本地部署 ComfyUI+Flux.1 模型!5 分钟搭建远程 AI 绘图服务器(保姆级教程)

文章目录 前言1. 本地部署ComfyUI2. 下载 Flux.1 模型3. 下载CLIP模型4. 下载 VAE 模型5. 演示文生图6. 公网使用 Flux.1 大模型6.1 创建远程连接公网地址 7. 固定远程访问公网地址 前言 在如今这 AI 技术一路火花带闪电、疯狂往前冲的时代&#xff0c;图像生成模型那可不再是…...

ABC398题解

A 算法标签: 模拟 #include <iostream> #include <algorithm> #include <cstring>using namespace std;const int N 110;int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int n;cin >> n;string res;if (n % 2) {int mid n / 2;f…...

数据通信——计算机基础

通信系统的组成 通信系统是指从一个地方向另外一个地方传递和交换信息&#xff0c;实现信息传递所需的一切技术设备和传输媒体的总和。通信系统一般由信源、发送设备、信道、接收设备、信宿以及噪声源组成&#xff0c;以下是各部分的具体介绍&#xff1a; 信源 信源是产生各…...

量子计算与人工智能的融合:下一代算力革命

1. 引言&#xff1a;算力需求的飞速增长与量子计算的潜力 在信息技术飞速发展的今天&#xff0c;人工智能&#xff08;AI&#xff09;已经渗透到我们生活的方方面面&#xff0c;从智能助手到自动驾驶&#xff0c;再到医疗诊断&#xff0c;AI 的应用场景日益广泛。然而&#xf…...

神经网络解决非线性二分类

这份 Python 代码实现了一个简单的神经网络&#xff0c;用于解决复杂的非线性二分类问题。具体步骤包含生成数据集、定义神经网络模型、训练模型、测试模型以及可视化决策边界。 依赖库说明 python import numpy as np import matplotlib.pyplot as plt from sklearn.datase…...

nuxt3网站文章分享微信 ,QQ功能

1.安装 npm install qrcode --save-dev 2.组件使用 <div class"share"><div style"line-height: 69px; color: #fff;width: 100px;"><p style"text-align: center;">分享:</p></div><div click"shareToMi…...

深入理解Spring框架:核心概念与组成剖析

引言 在Java企业级开发领域&#xff0c;Spring框架无疑是当之无愧的王者。自2003年首次发布以来&#xff0c;Spring凭借其强大的功能、高度的灵活性和卓越的扩展性&#xff0c;已成为构建大型企业应用程序的首选框架。本文将深入探讨Spring框架的核心概念与多样组成部分&#…...

Ubuntu22.04美化MacOS主题

安装Tweaks 参考Ubuntu 22.04 桌面美化成Mac风格这篇更好点 sudo apt install gnome-tweaks gnome-shell-extensions -y安装macos主题 git clone https://github.com/vinceliuice/WhiteSur-gtk-theme.git # 进到文件目录 ./install.sh -t all -N glassy sudo ./tweaks.sh -g…...

MySQL: 创建两个关联的表,用联表sql创建一个新表

MySQL: 创建两个关联的表 建表思路 USERS 表&#xff1a;包含用户的基本信息&#xff0c;像 ID、NAME、EMAIL 等。v_card 表&#xff1a;存有虚拟卡的相关信息&#xff0c;如 type 和 amount。关联字段&#xff1a;USERS 表的 V_CARD 字段和 v_card 表的 v_card 字段用于建立…...

JavaScript 中for...in和for...of循环的原理区别,在遍历对象和数组时分别如何使用

大白话JavaScript 中for…in和for…of循环的原理区别&#xff0c;在遍历对象和数组时分别如何使用 嘿&#xff0c;朋友&#xff01;咱来唠唠 JavaScript 里 for...in 和 for...of 这两种循环的事儿。它们就像是两个不同的小帮手&#xff0c;能帮你在对象和数组里溜达溜达&…...

图解AUTOSAR_SWS_WatchdogInterface

AUTOSAR Watchdog Interface (WdgIf) 详解 AUTOSAR经典平台看门狗接口模块技术详解 目录 1. 概述 1.1 WdgIf模块的作用1.2 WdgIf在AUTOSAR中的位置2. 架构设计 2.1 WdgIf架构概览2.2 接口设计2.3 序列设计3. 配置详解 3.1 配置参数3.2 配置结构3.3 配置类型4. 总结 4.1 主要特点…...

快速搭建yolo测试环境,超简明的神经网络训练说明书

1 快速搭建yolo测试环境 相对于更早的版本&#xff0c;v5是比较舒服的&#xff0c;直接把仓库拉下来就行&#xff0c;不用单独搞测试脚本和权重文件 $ git clone https://github.com/ultralytics/yolov5.git然后就是切到目录下安装依赖的第三方库&#xff1a; $ cd yolov5 $…...

如何在IDEA中借助深度思考模型 QwQ 提高编码效率?

通义灵码上新模型选择功能&#xff0c;不仅引入了 DeepSeek 满血版 V3 和 R1 这两大 “新星”&#xff0c;Qwen2.5-Max 和 QWQ 也强势登场&#xff0c;正式加入通义灵码的 “豪华阵容”。开发者只需在通义灵码智能问答窗口的输入框中&#xff0c;单击模型选择的下拉菜单&#x…...

探索 Ollama:开源大语言模型平台的无限可能​

在人工智能的快速发展进程中&#xff0c;大语言模型扮演着至关重要的角色。Ollama 作为一个开源的大语言模型平台&#xff0c;正逐渐崭露头角&#xff0c;为广大开发者和爱好者带来了全新的体验。它允许用户在本地环境中轻松地运行、创建和共享大型语言模型&#xff0c;极大地降…...

clickhouse多条件查询

安装包 infi.clickhouse-orm 2.1.3建表 create table test.test (name String,age UInt32,birthday Date32,sex UInt8 ) engineMergeTree() order by (name,sex)insert into test.testvalues (aa,34,1991-01-19,1), (cc,30,1994-01-19,0), (haha,31,1994-02-19,0);多条件查询…...

信息的度量

系列文章目录 文章目录 系列文章目录一、离散消息的信息量1.自信息的引入2.自信息定义 二、离散信源的平均信息量---信息熵1.信息熵定义 一、离散消息的信息量 1.自信息的引入 通信的本质是传递信息&#xff0c;为了定量表征信息的度量&#xff0c;引入自信息量的概念。事件包…...

ffmpeg+QOpenGLWidget显示视频

​一个基于 ‌FFmpeg 4.x‌ 和 QOpenGLWidget的简单视频播放器代码示例&#xff0c;实现视频解码和渲染到 Qt 窗口的功能。 1&#xff09;ffmpeg库界面&#xff0c;视频解码支持软解和硬解方式。 硬解后&#xff0c;硬件解码完成需要将数据从GPU复制到CPU。优先采用av_hwf…...

从零开始实现 C++ TinyWebServer 项目总览

文章目录 引言Web Server 概念如何实现高性能 WebServer&#xff1f;基础网络通信I/O 多路复用技术并发处理事件处理模式其他优化策略&#xff08;未实现&#xff09; 主要功能模块BufferLogSqlConnectPoolHttpRequestHttpResponseHttpConnectHeapTimerWebServer 引言 TinyWeb…...

opencv无法读取的图像,利用pil和numpy进行修复

代码总结 这段代码的功能是遍历指定文件夹下的所有图像文件&#xff0c;并修复可能存在的格式问题&#xff0c;然后覆盖原图像。 代码解析 设置输入文件夹路径&#xff08;input_folder&#xff09;。遍历文件夹中的所有文件&#xff0c;筛选出 .jpg、.jpeg、.png、.webp 格式…...

Redis分布式寻址算法

分布式寻址算法是分布式系统中用于确定数据应该存储在哪个节点的算法。这些算法对于实现高效的数据存取、负载均衡和系统扩展性至关重要。以下是几种常见的分布式寻址算法的解释&#xff1a; 1. Hash 算法 原理&#xff1a;通过哈希函数将数据的键&#xff08;Key&#xff09…...

CUDA 学习(1)——GPU 架构

典型 CPU 架构与 GPU 架构对比&#xff1a; 上图中绿色部分是计算单元&#xff0c;GPU 有更多的计算核心&#xff0c;计算能力更强。黄色部分是控制单元&#xff0c;CPU 中有大量的控制单元&#xff0c;现代 CPU 的晶体管越来越复杂&#xff0c;除了计算&#xff0c;还要实现乱…...

5个视角、5等级及10档次:《数字化转型领域 参考架构》国家标准正式出台

近日&#xff0c;国家标准GB/T 45341-2025《数字化转型管理 参考架构》正式出台。这是我国研制的首个数字化转型领域基础架构类国家标准&#xff0c;对数字化转型领域标准化建设具有重大意义。 关注WeChat Subscription Account【智慧城市指北】&#xff0c;回复关键字“20250…...