webrtc 源码阅读 make_ref_counted模板函数用法
目录
1. 模板参数解析
1.1 typename T
1.2 typename... Args
1.3 typename std::enable_if::value, T>::type* = nullptr
2. scoped_refptr
3. new RefCountedObject(std::forward(args)...);
4. 综合说明
5.在webrtc中的用法
5.1 peerConnectionFactory对象的构建过程
先看make_ref_counted模板函数的定义
template <typename T,typename... Args,typename std::enable_if<std::is_convertible<T*, RefCountInterface*>::value,T>::type* = nullptr>
scoped_refptr<T> make_ref_counted(Args&&... args) {return new RefCountedObject<T>(std::forward<Args>(args)...);
}
template <class T>
class RefCountedObject : public T {public:RefCountedObject() {}template <class P0>explicit RefCountedObject(P0&& p0) : T(std::forward<P0>(p0)) {}template <class P0, class P1, class... Args>RefCountedObject(P0&& p0, P1&& p1, Args&&... args): T(std::forward<P0>(p0),std::forward<P1>(p1),std::forward<Args>(args)...) {}void AddRef() const override { ref_count_.IncRef(); }RefCountReleaseStatus Release() const override {const auto status = ref_count_.DecRef();if (status == RefCountReleaseStatus::kDroppedLastRef) {delete this;}return status;}// Return whether the reference count is one. If the reference count is used// in the conventional way, a reference count of 1 implies that the current// thread owns the reference and no other thread shares it. This call// performs the test for a reference count of one, and performs the memory// barrier needed for the owning thread to act on the object, knowing that it// has exclusive access to the object.virtual bool HasOneRef() const { return ref_count_.HasOneRef(); }protected:~RefCountedObject() override {}mutable webrtc::webrtc_impl::RefCounter ref_count_{0};RTC_DISALLOW_COPY_AND_ASSIGN(RefCountedObject);
};
WebRTC 源码中的一个 make_ref_counted
函数模板,它用于创建具有引用计数的对象。通过使用 C++ 的 SFINAE(Substitution Failure Is Not An Error)和 std::enable_if
,该函数确保只有在某些条件下才能创建对象,这些条件是 T
类型必须能够转换为 RefCountInterface*
。
对如上源码解读:
1. 模板参数解析
1.1 typename T
T
是模板的类型参数,表示要创建的对象类型。例如,如果你想创建一个MyClass
类型的对象,则T
将是MyClass
。
1.2 typename... Args
Args
是一个 可变模板参数,表示你可以传入任意数量的构造函数参数。这使得make_ref_counted
可以用于创建任何带有不同构造参数的对象。
1.3 typename std::enable_if<std::is_convertible<T*, RefCountInterface*>::value, T>::type* = nullptr
-
这一部分使用了 SFINAE 技巧来约束模板的实例化条件。通过
std::enable_if
和std::is_convertible
,它确保只有当T*
(即T
类型的指针)能够转换为RefCountInterface*
类型时,才会启用该模板。std::is_convertible<T*, RefCountInterface*>::value
是一个类型特性(type trait),它检查类型T*
是否可以转换为RefCountInterface*
。如果可以转换,表达式的值为true
,否则为false
。- 如果
T*
可以转换为RefCountInterface*
,则std::enable_if
会定义类型别名type
,从而允许模板实例化。 - 如果
T*
不能转换为RefCountInterface*
,则模板实例化将失败,不会生成该函数。
-
std::enable_if<Condition, T>::type*
:当条件成立时,enable_if
会提供一个类型别名type
,而type*
是指向T
类型的指针。= nullptr
是默认参数,表示type*
参数是一个指针类型且值为nullptr
。
2. scoped_refptr<T>
-
scoped_refptr<T>
是 WebRTC 中的智能指针,用于管理引用计数对象的生命周期。它会在对象超出作用域时自动减少引用计数,如果引用计数降到零,T
类型的对象会被销毁。在这段代码中,
scoped_refptr<T>
被用作返回类型,表示make_ref_counted
函数会返回一个智能指针,管理创建的对象。
3. new RefCountedObject<T>(std::forward<Args>(args)...);
-
new RefCountedObject<T>(std::forward<Args>(args)...);
会创建一个新的RefCountedObject<T>
对象,并传递参数args
给其构造函数。RefCountedObject<T>
是一个继承自RefCountInterface
的类,用于为对象提供引用计数功能。-
std::forward<Args>(args)...
:这个语法用于完美转发参数。如果Args
是一个左值引用类型,那么它会以左值方式传递;如果是右值,则会以右值方式传递。完美转发保证了参数的传递不发生不必要的拷贝或移动。 -
RefCountedObject<T>
是 WebRTC 中专门为引用计数管理而设计的一个模板类,它负责管理T
类型的对象的生命周期。当scoped_refptr<T>
被销毁时,它会自动减少RefCountedObject<T>
的引用计数。
-
4. 综合说明
整个函数的作用是创建一个 T
类型的对象,并将其包装在一个具有引用计数的智能指针(scoped_refptr<T>
)中。它的关键是通过 std::enable_if
限制,只有当 T
类型能够转换为 RefCountInterface*
时,才会进行实例化,确保只有支持引用计数的对象才会被创建。
5.在webrtc中的用法
5.1 peerConnectionFactory对象的构建过程
从webrtc源码看peerConnectionFactory类的继承关系如下图所示。它公有继承自PeerConnectionFactoryInterface(抽象类),而PeerConnectionFactoryInterface又公有继承自RefCountInterface(抽象类)。peerConnectionFactory并没有实现父抽象类的虚函数,所以peerConnectionFactory也是一个抽象类,那是如何创建出peerConnectionFactory对象呢?
如下代码是webrtc创建peerConnectionFactory对象的位置,
rtc::scoped_refptr<PeerConnectionFactory> PeerConnectionFactory::Create(PeerConnectionFactoryDependencies dependencies) {auto context = ConnectionContext::Create(&dependencies);if (!context) {return nullptr;}return rtc::make_ref_counted<PeerConnectionFactory>(context, &dependencies);
}
根据上述对make_ref_counted的介绍,因为PeerConnectionFactory类型可以转换成RefCountInterface*类型,
new RefCountedObject<T>(std::forward<Args>(args)...);
所以如上这行代码,是把peerConnectionFactory类型当做模版类型T传入。展开后的代码应该长这样:
new RefCountedObject<peerConnectionFactory>(context, &dependencies);
对于模板类RefCountedObject,内部实现了RefCountInterface抽象类的两个接口。
template <class T>
class RefCountedObject : public T {public:RefCountedObject() {}template <class P0>explicit RefCountedObject(P0&& p0) : T(std::forward<P0>(p0)) {}template <class P0, class P1, class... Args>RefCountedObject(P0&& p0, P1&& p1, Args&&... args): T(std::forward<P0>(p0),std::forward<P1>(p1),std::forward<Args>(args)...) {}void AddRef() const override { ref_count_.IncRef(); }RefCountReleaseStatus Release() const override {const auto status = ref_count_.DecRef();if (status == RefCountReleaseStatus::kDroppedLastRef) {delete this;}return status;}// Return whether the reference count is one. If the reference count is used// in the conventional way, a reference count of 1 implies that the current// thread owns the reference and no other thread shares it. This call// performs the test for a reference count of one, and performs the memory// barrier needed for the owning thread to act on the object, knowing that it// has exclusive access to the object.virtual bool HasOneRef() const { return ref_count_.HasOneRef(); }protected:~RefCountedObject() override {}mutable webrtc::webrtc_impl::RefCounter ref_count_{0};RTC_DISALLOW_COPY_AND_ASSIGN(RefCountedObject);
};
所以调用
rtc::scoped_refptr<PeerConnectionFactory> PeerConnectionFactory::Create(
PeerConnectionFactoryDependencies dependencies) {
auto context = ConnectionContext::Create(&dependencies);
if (!context) {
return nullptr;
}
return rtc::make_ref_counted<PeerConnectionFactory>(context, &dependencies);
}
后,接着调用rtc::make_ref_counted模版函数后,在这个模版函数内是new一个模版类,这个模版类的参数类型是PeerConnectionFactory。
new RefCountedObject<T>(std::forward<Args>(args)...);
最终看到的PeerConnectionFactory对象,其实是在其外部又封装了一层。这样做的好处是PeerConnectionFactory对象会在其生命期结束后释放对象,实现这个功能主要是靠rtc::scoped_refptr实现的。有时间再接着介绍rtc::scoped_refptr。
从下图可以看出创建的peerConnectionFactory对象确实是来自模板类RefCountedObject。
类似PeerConnection类、EncoderStreamFactory类、 VideoRtpSender类等都是采用这种方式初始化对象的
相关文章:
webrtc 源码阅读 make_ref_counted模板函数用法
目录 1. 模板参数解析 1.1 typename T 1.2 typename... Args 1.3 typename std::enable_if::value, T>::type* nullptr 2. scoped_refptr 3. new RefCountedObject(std::forward(args)...); 4. 综合说明 5.在webrtc中的用法 5.1 peerConnectionFactory对象的构建过…...
僵尸进程,孤儿进程、守护进程以及wait函数,waitpid函数
僵尸进程 如果子进程退出,但是父进程没有调用 wait 或 waitpid 获取子进程的状态信息,那么子进程的进程描述符(task_struct)仍然保存在系统中,那么该子进程叫做僵尸进程 #include<iostream> #include<pthre…...
Kafka消息不丢失与重复消费问题解决方案总结
1. 生产者层面 异步发送与回调处理 异步发送方式:生产者一般使用异步方式发送消息,异步发送有消息和回调接口两个参数。在回调接口的重写方法中,可通过异常参数判断消息发送状态。若消息发送成功,异常参数为null;若发…...
Docker新手:在tencent云上实现Python服务打包到容器
1 使用docker的原因 一致性和可移植性:Docker 容器可以在任何支持 Docker 的环境中运行,无论是开发者的笔记本电脑、测试服务器还是生产环境。这确保了应用在不同环境中的行为一致,减少了“在我的机器上可以运行”的问题。 隔离性ÿ…...
什么是 Spring 的组件(Bean)
什么是 Spring 的组件(Bean)? Spring 会自动创建、初始化、装配和销毁这些对象。Spring 使用 IoC(控制反转) 和 DI(依赖注入) 的理念,将应用程序的对象交给 Spring 容器统一管理&am…...
PawSQL性能巡检平台 (3) - 慢查询采集和优化
在数据库运维管理中,慢查询一直是影响系统性能的重要因素。本文将详细介绍PawSQL数据库性能巡检平台在慢查询管理和优化方面的功能特性,帮助数据库管理员更好地应对性能挑战。 一、PawSQL巡检平台慢查询管理概述 PawSQL平台提供了全面的慢查询管理功能&…...
虚拟机Centos下安装Mysql完整过程(图文详解)
目录 一. 准备工作 1. 设置虚拟机静态IP 2. 卸载Mysql 3. 给CentOS添加rpm源 二. 安装MySQL 1. 安装mysql服务 2. 启动mysql服务 3. 开启MySQL开机自启动 4. 查看mysql服务状态 5. 查看mysql初始密码 6. 登录mysql ,修改密码 7. 允许外部访问MySQL数据库…...
微服务保护-sentinel
为什么要有微服务保护? 微服务保护是为了避免微服务雪崩而出现的,每个微服务能处理的请求是有限的,如果一个微服务出现问题导致一个请求进入微服务的时间太久,就会导致大量去请求停滞在微服务内部,这样就会过分占用系统…...
Redis Java 集成到 Spring Boot
Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~ 🌱🌱个人主页:奋斗的明志 🌱🌱所属专栏:Redis 📚本系列文章为个人学习笔…...
RabbitMQ实现生产者消费者
一.启动MQ 注意管理员身份进入cmd才行,我这里是在本地安装的MQ,推荐使用虚拟机安装 二.思路 官方解释RabbitMQ结构: 自我理解RabbitMQ结构: 其实RabbitMQ的服务器就像邮局一样,我们的生产者和消费者对于这个服务器来说都是消费者,因为服务器都可以向两者发送消息 环境准备 …...
stm32f103zet6 ds18b20
main.c // main.c #include "sys.h" #include "ds18b20.h"int main(void){ uart_init(9600);delay_init();while(DS18B20_Init()) //DS18B20初始化 {printf("error");delay_ms(200);}while(1){printf("%4.2f\r\n",Get_Temp());}}ds18…...
期权懂|期权入门知识:开通50ETF期权需要什么条件?
锦鲤三三每日分享期权知识,帮助期权新手及时有效地掌握即市趋势与新资讯! 开通50ETF期权需要什么条件? 一、基本资格要求 (1)年龄限制:投资者必须年满18周岁,具备完全民事行为能力。 &#…...
Linux day 1129
家人们今天继续学习Linux,ok话不多说一起去看看吧 三.Linux常用命令 3.1 Linux命令体验 3.1.1 常用命令演示 在这一部分中,我们主要介绍几个常用的命令,让大家快速感 受以下 Linux 指令的操作方式。主要包含以下几个指令: ls命…...
智能家居体验大变革 博联 AI 方案让智能不再繁琐
1. 全球AI技术发展背景及智能家居市场趋势 人工智能(AI)技术的飞速发展正在推动全球各行业的数字化转型。国际电信联盟与德勤联合发布《人工智能向善影响》报告指出,全球94%的商界领袖认为,人工智能技术对于其企业在未来5年内的发…...
git使用
git初始化 git init 指定要添加的文件 git add [文件名1] [文件名2] [文件名3] // 添加指定文件 git add . // 添加当前目录所有文件 将文件提交到本地仓库 git commit -m "备注信息" 添加远程仓库 git remote add origin [远程仓库地址] git remote -v // …...
嵌入科技的温情
嵌入式世界,是一个微小却无比精妙的宇宙。晶体管之间的脉动,仿佛是心跳的回响;代码中跳跃的逻辑,犹如人生中不可预知的转折。每一个嵌入式系统,都像是一个看不见的灵魂,将冰冷的机器唤醒,为生活…...
python利用selenium实现大麦网抢票
大麦网(damai.cn)是中国领先的现场娱乐票务平台,涵盖演唱会、音乐会、话剧、歌剧、体育赛事等多种门票销售。由于其平台上经常会有热门演出,抢票成为许多用户关注的焦点。然而,由于票务资源的有限性,以及大…...
PS等软件学习笔记
目录 一、ps基础操作快捷键 1、快速打开图片 2、屏幕画布变大变小 3、移动画布 4、CTRL回车,快速完成更改 5、还原 6、创建画布,CTRLN 7、复制图层,CTRLJ 8、一段文字行间距调整 9、反向选择,CTRLSHIFTI 10、抠图 二、…...
vue3学习笔记(9)-pinia、storeToRefs、getters
1.新的集中式状态(数据)管理库,redux vuex pinia 搭建 2.ref拆包 如果在reactive里面定义ref,则打印c时,无需.value 他自动拆包,如果直接在外面定义的ref则需要.value,他没有拆包 3.pinia存储读取数据 存…...
数据库基础知识---以MySQL为例
一、什么是MySQL 数据保存在不同的表中,而不是将所有数据放在一个大仓库内 二、特点 开源--免费下载跨平台--可以在多个操作系统进行运行性能好--可以出来大量数据简单--安装配置简单支持多种编程语言--可以与多种编程语言进行无缝集成 三、分类 DDL--数据定义…...
013-spring的注解整合第三方框架
给spring的ioc容器中添加对象 常用这3个方法...
使用ForceBindIP绑定应用到指定IP
前言 使用ForceBindIP工具,用户可以轻松地将特定应用程序绑定到指定的IP地址,从而确保应用程序的网络连接通过指定的网络适配器进行。通过在命令提示符下运行ForceBindIP并指定IP地址和应用程序的完整路径,用户能够控制应用程序的网络流量&a…...
python-LeetCode-两数之和
1. 两数之和 - 力扣(LeetCode) class Solution:def twoSum(self, nums: List[int], target: int) -> List[int]:# 创建一个哈希表用于存储值和索引num_to_index {}for i, num in enumerate(nums):# 计算目标值需要的补数complement target - num# 如…...
项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(四)
文章目录 一、管理员角色功能实现1、添加教师功能实现1.1 页面设计1.2 前端功能实现1.3 后端功能实现1.4 效果展示2、教师管理功能实现2.1 页面设计2.2 前端功能实现2.3 后端功能实现2.3.1 后端查询接口实现2.3.2 后端编辑接口实现2.3.3 后端删除接口实现2.4 效果展示二、代码下…...
大语言模型的token和向量
现在大语言模型火了,像 ChatGPT 什么的,能回答问题、写文章,。但它们为啥这么聪明呢?这就和向量、Token 有关系。那怎么通过向量、Token来理解我们的问题呢。看完这篇文章就知道了 token Token 就像是语言里的小积木,…...
Hyperledger Fabric有那些核心技术,和其他区块链对比Hyperledger Fabric有那些优势
Hyperledger Fabric是一个模块化、权限化的企业级区块链平台,与比特币、以太坊等公有链相比,Fabric主要为私有链或联盟链设计,适用于企业应用。它包含多项核心技术,使其在企业级区块链应用中具有独特优势。以下是Fabric的核心技术…...
ThinkPHP 8高效构建Web应用-第一个简单的MVC应用示例
【图书介绍】《ThinkPHP 8高效构建Web应用》-CSDN博客 《2025新书 ThinkPHP 8高效构建Web应用 编程与应用开发丛书 夏磊 清华大学出版社教材书籍 9787302678236 ThinkPHP 8高效构建Web应用》【摘要 书评 试读】- 京东图书 使用VS Code开发ThinkPHP项目-CSDN博客 我们先实现一…...
【Goland】怎么执行 go mod download
1、终端的执行 go mod tidy 2、终端执行不行的话,就可以通过右击go.mod文件来执行; 3、也可以按住Ctrl点击这个包安装;...
SpringBoot入门案例
目录 一、SpringBoot入门 1. Spring Boot 简介(脚手架) 2. 微服务 微服务优点: 微服务缺点: 3. 环境准备 3.1 spring boot项目的创建 3.2 导入spring boot相关的依赖 3.5 编写主程序 3.4 编写相关的controller、service…...
自定义 Celery的logging模块
为什么需要自定义 Celery 日志 默认的 Celery 日志配置虽然满足基本需求,但在以下情况下可能需要进行自定义: 支持日志滚动:原生celery不支持日志滚动。更详细的日志信息:需要包含更多上下文信息,以便更好地理解任务…...
docker-开源nocodb,使用已有数据库
使用已有数据库 创建本地数据库 数据库:nocodb 用户:nocodb 密码:xxxxxx修改docker-compose.yml 默认网关的 IP 地址是 172.17.0.1(适用于 bridge 网络模式)version: "2.1" services:nocodb:environment:…...
【UE5】UnrealEngine源码构建1:tag为5.3.2源码clone
fatal: fetch-pack: invalid index-pack output clone unreal 速度很快,但是很容易失败Cloning into UnrealEngine... remote: Enumerating objects: 6511087, done. remote: Counting objects: 100% (196/196), done. remote: Compressing objects: 100% (50/50), done. erro…...
RoboMIND:多体现基准 机器人操纵的智能规范数据
我们介绍了 RoboMIND,这是机器人操纵的多体现智能规范数据的基准,包括 4 个实施例、279 个不同任务和 61 个不同对象类别的 55k 真实世界演示轨迹。 工业机器人企业 埃斯顿自动化 | 埃夫特机器人 | 节卡机器人 | 珞石机器人 | 法奥机器人 | 非夕科技 | C…...
FPGA自学之路:到底有多崎岖?
FPGA,即现场可编程门阵列,被誉为硬件世界的“瑞士军刀”,其灵活性和可编程性让无数开发者为之倾倒。但谈及FPGA的学习难度,不少人望而却步。那么,FPGA自学之路到底有多崎岖呢? 几座大山那么高?…...
讲一个自己写的 excel 转 html 的 java 工具
由来 这是一个从开发需求中诞生的工具,在工作中因为有一个 excel 转 html 的任务,又没找到一个专门做这方面的工具(其他工具几乎都是简单的转换,无法还原 excel 样式,而且转换的宽高有点儿差距)࿰…...
打破视障壁垒,百度文心快码无障碍版本助力视障IT从业者就业无“碍”
有AI无碍 钟科:被黑暗卡住的开发梦 提起视障群体的就业,绝大部分人可能只能想到盲人按摩。但你知道吗?视障人士也能写代码。 钟科,一个曾经“被黑暗困住”的人,他的世界,因为一场突如其来的疾病,…...
爆改RagFlow
爆改RagFlow 一、Rag理论概述二、Ragflow解析参数说明三、♥ RagFlow源码解析核心代码流程梳理1、OCR识别2、版面分析3、parser功能3.1 PdfParser3.1.1 首先,初始化3.1.2 **pdf转图片** [来自工业界的知识库 RAG 服务(二),RagFlow 源码全流程深度解析](h…...
Unity 使用UGUI制作卷轴开启关闭效果
视频效果 代码 using UnityEngine.UI; using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; using DG.Tweening.Core; using DG.Tweening.Plugins.Options;public class JuanZhou : MonoBehaviour {[SerializeField]private …...
android知识巩固(二.非线性数据结构)
非线性结构:是从逻辑结构上划分,其元素存在一对多或者多对多的相互关系 1.前言 在前一章中,我们了解了数据结构的基本思想,学习了部分基本的线性数据结构,了解了计算机是如何表示和存储数据的,良好的数据结构思想有助于我们写出性能优良的应用 2.目录 目录.png 3.非线性数据结构…...
Kafka中的Topic和Partition有什么关系?
大家好,我是锋哥。今天分享关于【Kafka中的Topic和Partition有什么关系?】面试题。希望对大家有帮助; Kafka中的Topic和Partition有什么关系? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Apache Kafka 中&#…...
CMS漏洞靶场攻略
DeDeCMS 环境搭建 傻瓜式安装 漏洞一:通过文件管理器上传WebShel 步骤⼀:访问目标靶场其思路为 dedecms 后台可以直接上传任意文件,可以通过⽂件管理器上传php文件获取webshell 登陆网站后台 步骤二:登陆到后台点击 【核心】 --》 【文件式…...
PHP高性能webman管理系统EasyAdmin8
介绍 EasyAdmin8-webman 在 EasyAdmin 的基础上使用 webman 最新版重构,PHP 最低版本要求不低于 8.0。基于webman和layui v2.9.x的快速开发的后台管理系统。 项目地址:http://easyadmin8.top 演示地址:http://webman.easyadmin8.top/admin …...
【达梦数据库】64 位操作系统注册 32 位 ODBC 方法
目录 背景思路部署安装64位软件安装包注册32位驱动成功案例其他案例 配置数据源 背景 在使用达梦数据库的过程中,应用需要32位驱动与数据库进行适配 思路 部署32位软件,经过测试,dmmonitor在本地环境及客户环境中前台启动失败报错ÿ…...
渗透学习笔记(十一)Burp Suite 总结
声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&#…...
数据结构与算法学习笔记----约数
数据结构与算法学习笔记----约数 author: 明月清了个风 first publish time: 2024.12.30 ps⭐️主要是求约数,约数的个数,约数的和,涉及到算术基本定理的相关内容,第三题的讲解合并在第二题的思路里一起了。 Acwing 869. 试除法…...
PyAudio库基本知识详解——为自制PCM音频播放器做准备
前言 结合前段时间我们做的音频编解码器,这样我们就可以将获取到的ADPCM数据,转换成PCM数据,然后播放出来,得到一个完整的音频数据,因此,接下来几篇文章中,我们想做一个播放PCM格式的音频播放器…...
微信小程序 覆盖组件cover-view
wxml 覆盖组件 <video src"../image/1.mp4" controls"{{false}}" event-model"bubble"> <cover-view class"controls"> <cover-view class"play" bind:tap"play"> <cover-image class"…...
实战案例——ZooKeeper集群部署(新手教程超详细)
案例目标 了解ZooKeeper分布式应用程序协调服务使用3台机器搭建ZooKeeper集群使用ZooKeeper集群 案例分析 规划节点 ZooKeeper集群节点规划 Ip 主机名 节点 192.168.110.10 zookeeper1 集群节点 192.168.110.20 zookeeper2 集群节点 192.168.110.30 zookeeper3 …...
LeetCode 326 3的幂
如何判断一个整数是否为 3 的幂次方 在编程中,我们经常会遇到各种有趣的数学问题,今天就来探讨一个看似简单却又很有技巧性的问题:如何判断一个给定的整数是否是 3 的幂次方。 一、问题描述 给定一个整数 n,我们需要编写一个函数…...
智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之5
本文要点 前端 问题描述语言 本文继续完善 “描述” ---现在我们应该可以将它称为 “问题problem描述语言 ”。 它 通过对话框的question 引发 表征的issue 的“涌现” 最终 厘清应用程序的“problem”。即它合并了 ISO七层模型中的上面三层,通过将三层 分别形成…...