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

深入篇【C++】类与对象:再谈构造函数之初始化列表与explicit关键字

深入篇【C++】类与对象:再谈构造函数之初始化列表与explicit关键字

  • Ⅰ.再谈构造函数
    • ①.构造函数体赋值
    • ②.初始化列表赋值
      • 【<特性分析>】
        • 1.至多性
        • 2.特殊成员必在性
        • 3.必走性:定义位置
        • 4.一致性
        • 5.不足性
  • Ⅱ.explicit关键字
    • ①.隐式类型转化
    • ②.作用

在这里插入图片描述

Ⅰ.再谈构造函数

我们知道在创建对象时,编译器会通过调用构造函数,给对象中各个成员变量一个合适的初始值。

也就是我们可以通过构造函数来给对象中的成员变量赋值。不过给成员变量赋值其实有两种方式,一种就是在函数体内进行赋值,另一种是在初始化列表赋值。函数体内赋值我们是知道什么意思,那什么叫初始化列表呢?
我们知道创建一个对象,什么表示对象创建出来了呢?
对象实例化表示对象已经创建出来,这是对象整体定义的地方,然后对象就会调用构造函数进行初始化。
对象定义的地方是对象实例化,实例化后就会调用构造函数初始化。
那想一想对象成员变量是在哪里定义的呢?
对象实例化只是对对象整体定义的地方,而初始化列表才是对象成员变量定义的地方。
只有定义完后才可以初始化。
所以初始化列表是对象成员定义的地方。

①.构造函数体赋值

对象实例化后就会调用构造函数初始化对象。
在函数体内部进行赋值初始化。

```handlebarsclass Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print()const{cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};

虽然上述构造函数调用之后,对象种已经有一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。
因为初始化只能初始化一次,但构造函数体内可以多次赋值。
本质上来说是因为对象成员变量不在函数体内定义,所以赋值后也不叫作初始化,只有在定义的地方赋值才可以叫做初始化,而对象成员变量定义的地方其实是初始化列表。

②.初始化列表赋值

初始化列表:以一个冒号开始,接着就是以一个逗号分割数据成员列表,每个成员变量后面跟上一个括号,括号里是初始值或者表达式。


class Date
{
public:Date(int year = 1, int month = 1, int day = 1)//这个就叫做初始化列表:_year(year)//以一个冒号开始,注意后面没有分号,_month(month)//逗号分割,_day(day)//每个成员变量后面都有一个括号,括号里是初始值或表达式{}
private:int _year;int _month;int _day;
};

【<特性分析>】

1.至多性

每个成员变量在初始化列表中至多出现一次,也可以不出现。
因为定义完后再初始化,而初始化只能初始化一次。
不出现的话那就会在函数体内进行初始化。

2.特殊成员必在性

类中包含以下成员时,必须放在初始化列表位置进行初始化。

  • 引用成员变量
  • const成员变量
  • 自定义类型成员(且该类没有默认构造函数时)

我们一个一个分析,为什么上面三个成员必须放在初始化列表初始化。
引用成员变量和const成员变量有什么特别之处呢?为什么会被要求放在初始化列表初始化呢?
引用成员变量和const成员变量都有一个特点:那就是在定义的时候必须初始化。
不然编译器会报错,而初始化列表正是变量定义的地方,在定义的地方给初始值才能成功的对引用成员变量和const成员变量初始化。如果在函数体内部进行赋值初始值,那这样不是初始化,因为函数体内部不是它们定义的地方,仅仅给个赋值是不能完成初始化的。


class B
{
public:B(int a, int ref)//初始化列表:成员变量定义的地方:_ref(ref)//引用, _n(1)//const修饰的{}
private:int& _ref;//引用成员变量//这两个特征就是必须在定义的时候就初始化const int _n;//const修饰的成员变量
};

第三种成员变量是自定义类型成员,并且当类中没有默认构造函数时,自定义类型成员必须放在初始化列表初始化,这是为什么呢?

class A
{
public:A(int a=0 )//有默认构造函数:_a(a){cout << "A(int a = 0)" << endl;}
private:int _a;
};
class B
{
public://初始化列表:对象的成员定义的地方B(int a, int ref):_ref(ref)//引用, _n(1)//const修饰的{}
private:A _obj;//有默认构造函数时,可以不用初始化int& _ref;const int _n;int _x = 1;
};

我们知道编译器生成的默认构造的工作是对自定义类型初始化,对内置类型不做处理。
所以当有默认构造函数时,自定义类型我们就不用去再初始化了。因为没有参数我也可以调用构造函数初始化。那没有默认构造函数呢?我们是不是就得手动给自定义类型成员变量进行初始化。但要注意的是函数体内不允许没有默认构造的自定义类型成员变量初始化,必须在初始化列表初始化。

在这里插入图片描述
道理其实是一样的,自定义类型在定义的时候也要进行初始化。
那怎么初始化呢? —调用构造函数。
如果有默认构造函数,那就可以之间使用默认构造函数初始化。
如果没有默认构造函数,那就必须在初始化列表进行初始化,因为初始化列表是成员变量定义的地方,如果要求在定义的时候进行初始化,那么必须得在初始化列表进行,函数体内部不是定义的地方,只是可以进行赋初始值,如果在函数体内部进行"初始化"其实是定义和赋初始值分开了,没有做到定义只是进行赋初始值。
而对于那些没有要求在定义时必须初始化的变量,既可以在初始化列表进行初始化,也可以在函数体内部进行初始化,可以做到定义和赋初始值分开。

class A
{
public:A(int a )//这个不是默认构造,这个是需要传参的构造函数:_a(a){cout << "A(int a = 0)" << endl;}
private:int _a;
};
class B
{
public://初始化列表:对象的成员定义的地方B(int a, int ref):_ref(ref)//引用, _n(1)//const修饰的,_obj(a)//自定义类型,无默认构造。{}
private:A _obj;//没有默认构造函数时,必须在初始化列表进行初始化。int& _ref;//引用const int _n;//const修饰的int _x = 1;};

要区分默认成员函数和默认构造函数:
1.默认成员函数是C++规定的几种特殊的成员函数,是不写编译器可以自动生成的,有默认构造函数,默认拷贝函数,默认赋值函数等等。而默认构造函数是包含在内的。
2.默认构造函数有三种:总的特征就是不用传参就可以使用的函数。
无参的构造函数+全缺省的构造函数+编译器生成的默认构造函数都叫做默认构造函数。
3.并且默认构造函数只能有一个。

所以当自定义类型成员变量类型没有默认构造函数时(三种默认构造函数,自己写的带有参数构造函数)在函数体内部赋初始值是无法通过的,必须在初始化列表显式初始化,去调用自己写的构造函数初始化。

也就是当没有提供默认构造函数的自定义类型,必须在初始化列表初始化。

3.必走性:定义位置

尽量使用初始化列表初始化,为什么呢?
因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会显示有初始化列表初始化,并且所有成员变量都会经过初始化列表的。因为初始化列表是成员变量定义的地方。
每个成员变量在初始化列表至多出现一次,但也可以不出现,不出现的意思是不给定义的变量赋初始值,但这个变量是在初始化列表定义的,只不过没有给初始值,其实所有的成员变量都会走初始化列表。

class B
{
public://初始化列表:对象的成员定义的地方B(int a, int ref):_ref(ref)//引用, _n(1)//const修饰的,_obj(a),_x(2)//对于那些没有要求必须在定义时初始化的既可以在初始化列表初始化{//_x=2;//也可以在函数体内部初始化}
private:A _obj;int& _ref;const int _n;int _x ;//初始化列表没有显式定义_x就会使用这个缺省值
};

比如上面的内置类型_x既可以在初始化列表初始化,又可以在函数体内部初始化,在初始化列表初始化就是定义时就初始化了,而在函数体内部初始化就是在初始化列表定义完后到函数体内赋初始值完成初始化。

class B
{
public://初始化列表:对象的成员定义的地方B(int a, int ref):_ref(ref)//引用, _n(1)//const修饰的,_obj(a){}
private:A _obj;int& _ref;const int _n;int _x=1 ;//这个1是缺省值,缺省值是给初始化列表的

你们还记得缺省值吧,C++给默认构造函数打补丁就规定了可以在成员变量声明时给缺省时,这样对于内置类型,也可以完成初始化了,那现在看来这个缺省值是如何完成初始化的呢?
其实这个缺省值就是给初始化列表用的,因为每个成员变量都会走初始化列表,初始化列表会将缺省值赋值给已经定义好的成员变量,这样成员变量就完成了初始化了。
当显式的初始化时,初始化列表会优先选取显式给的初始值,而放弃掉缺省值,当没有显式的初始化时,初始化列表就会将缺省值赋值给成员变量 。

4.一致性

成员变量在类中声明次序就是在其初始化列表中的初始化顺序。
声明的顺序对应着要初始化的顺序,必须要一致,不然会出现问题。
比如下面这个问题:

class A
{
public:A(int a):_a1(a), _a2(_a1){}void Print() {cout << _a1 << " " << _a2 << endl;}
private:int _a2;int _a1;
};
int main() {A aa(1);aa.Print();
}

这个结果是什么呢?
在这里插入图片描述
为什么呢?注意到成员变量声明的次序,_a2先声明,_a1后声明,则表明_a2先进行初始化,_a1后进行初始化
在这里插入图片描述

5.不足性

初始化列表的使用虽然很方便,但也有它不足之处,比如当有些赋值后的成员需要检查是否赋值成功,再比如要求对数组进行初始化,初始化列表就无法完成这样的工作。

class Stack
{
public:Stack(int capacity=10):_a((int*)malloc(sizeof(int)* capacity)),_top(0),_capacity(capacity){if (_a == nullptr){perror("malloc");//要求数组初始化一下memset(_a, 0, sizeof(int) * capacity);}}
private:int* _a;int _top;int _capacity
};

再比如写一个动态二维数组:初始化列表就无法完成这样的工作,必须借助函数体来解决,所以总有一些工作是初始化列表完成不了的,这时就需要和函数体一起协同工作了。

class AA
{
public:AA(int row = 10, int col = 5):_row(row), _col(col){_a = (int**)malloc(sizeof(int*) * row);for (int i = 0; i < row; i++){_a[i] = (int*)malloc(sizeof(int) * col);}}
private:int** _a;int _row;int _col;
};

Ⅱ.explicit关键字

①.隐式类型转化

构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值,其余均有默认值的构造函数,还具有类型转化的作用。

这其实就是隐式类型转化,看下面代码:

int main()
{int i = 0;double d1 = i;//这里发生了什么呢?
}

这里i是int类型,d1是double类型将i赋值给d1,会发生类型转化。发生什么样子的转化呢?
其实在这个过程中会生成一个临时变量,将i赋给临时变量,临时变量再赋给d1.
在这里插入图片描述

class A
{
public:A(int a):_a(a){}A(const A& a1){_a = a1._a;}
private:int _a;
};
int main()
{A aa1(1);A aa2 = 4;
}

对象aa1调用构造函数初始化成1,那对象aa2在干嘛呢?
对象aa2其实是将整形的4赋给aa2,这里就涉及了隐式类型转化,将int类型隐式转换成A类型。
这里其实是4调用构造函数,构造一个A类型的临时对象,然后临时对象再拷贝构造给aa2。只不过编译器将这两步优化成一步,优化成直接构造。

如果不相信的话可以看看下面的代码:

int main()
{A aa1(1);A& aa2 = 4;
}

用对象aa2来引用4可以吗?在这里插入图片描述
这里肯定不行呀,这两个类型都不一样肯定不能引用。
但只要给对象aa2前面加上const修饰那么这样就可以引用了,这是为什么呢?
在这里插入图片描述

不知道你还记得临时变量具有常性这个特点吗?
正是因为这个特点,加上const修饰后就允许引用了,因为4会调用构造函数,构造出一个A类型的临时变量,而因为临时变量具有常性,相比较正常的A类型权限缩小了,所以不能相互引用,但一旦加上const修饰后,权限相同,就可以相互引用了。
所以在隐式类型转化时会产生一个临时变量的。

②.作用

如果不想在调用构造函数时构造出一个临时变量的话,就可以用关键字explicit。

使用explicit后构造函数就无法构造出临时变量了,这样的隐式类型转化就不会发生了。

class A
{
public:explicit A(int a):_a(a){}A(const A& a1){_a = a1._a;}
private:int _a;
};
int main()
{A aa1(1);A aa2 = 4;
}

在这里插入图片描述

相关文章:

深入篇【C++】类与对象:再谈构造函数之初始化列表与explicit关键字

深入篇【C】类与对象&#xff1a;再谈构造函数之初始化列表与explicit关键字 Ⅰ.再谈构造函数①.构造函数体赋值②.初始化列表赋值【<特性分析>】1.至多性2.特殊成员必在性3.必走性&#xff1a;定义位置4.一致性5.不足性 Ⅱ.explicit关键字①.隐式类型转化②.作用 Ⅰ.再谈…...

广东棒球发展建设·棒球1号位

一、概述 棒球是一项源于美国的运动&#xff0c;自20世纪初开始传入中国&#xff0c;近年来在广东省的发展也逐渐受到关注。本文将就广东棒球的发展现状及未来发展方向进行分析。 二、发展现状 目前广东省内棒球赛事主要有以下几种&#xff1a; 1. 业余棒球联赛&#xff1a;…...

浅谈PMO对组织战略的支持︱美团骑行事业部项目管理中心负责人边国华

美团骑行事业部项目管理中心负责人边国华先生受邀为由PMO评论主办的2023第十二届中国PMO大会演讲嘉宾&#xff0c;演讲议题&#xff1a;浅谈PMO对组织战略的支持。大会将于6月17-18日在北京举办&#xff0c;更多内容请浏览会议日程 议题内容简要&#xff1a; 战略是组织运行的…...

互联网医院资质代办|互联网医院牌照的申请流程

随着互联网技术的不断发展&#xff0c;互联网医疗已经逐渐成为人们关注的热点话题。而互联网医院作为互联网医疗的一种重要形式&#xff0c;也越来越受到社会各界的关注。若想开展互联网医院业务&#xff0c;则需要具备互联网医院牌照。那么互联网医院牌照的申请流程和需要的资…...

网络:DPDK复习相关知识点_2

1.RTC运行至完成时模式&#xff0c;单核单模块 2.pipeline模式&#xff0c;多核多模块&#xff0c;每个模块都是一个处理引擎&#xff0c;但会有缓存一致性问题 3.Mbuff数据包内存操作对象&#xff0c;相当于是数据包的一个索引&#xff0c;对网络的处理都集中在这个Buff上 …...

阿里云大学考试Java中级题目及解析-java中级

阿里云大学考试Java中级题目及解析 1.servlet释放资源的方法是&#xff1f; A.int()方法 B.service()方法 C.close() 方法 D.destroy()方法 D servlet释放资源的方法是destroy() 2.order by与 group by的区别&#xff1f; A.order by用于排序&#xff0c;group by用于排序…...

【星戈瑞】Sulfo-CY3-COOH磺化/水溶性Cyanine3羧酸1121756-11-3

Sulfo-CY3 COOH是一种荧光染料&#xff0c;其分子结构中含有COOH官能团&#xff0c;最大吸收波长为550纳米左右&#xff0c;可以通过分光光度计等设备进行检测。Sulfo-CY3 COOH是一种带有羧基的荧光染料&#xff0c;可以与含有氨基的生物分子通过偶联反应形成共价键&#xff0c…...

Java NIO和IO的主要区别

当学习了Java NIO和IO的API后&#xff0c;一个问题马上涌入脑海&#xff1a; 我应该何时使用IO&#xff0c;何时使用NIO呢&#xff1f;在本文中&#xff0c;我会尽量清晰地解析Java NIO和IO的差异、它们的使用场景&#xff0c;以及它们如何影响您的代码设计。 下表总结了Java N…...

SQL查询语句

DQL语句--排序查询 # 格式: select * from 表名 order by 要排序的列1 [asc/desc], 要排序的列2 [asc/desc]; # 解释: # 1. 无论SQL语句简单或者是复杂, order by语句一般都放最后, 注意: 如果有limit(分页), 则它(limit)在最后. # 2. asc表示升序, desc表示降序, 其中, 默…...

四象限法进程调度

周二收到一篇推送 一次云上网络毫秒级的优化与实践&#xff0c;很有意义的实践和探索&#xff0c;建议阅读&#xff0c;文章不长&#xff0c;没有冗长的源码分析&#xff0c;结论很清晰。 谈谈我的看法。 多少有种感觉&#xff0c;Linux 越来越像个响应系统而不是服务器。 虚…...

蓝桥杯拿到一等奖,并分享经验

昨天和群里的小伙伴在群里聊&#xff0c;有的小伙伴竟然说蓝桥杯一等奖没有含量&#xff0c;我也是醉了&#xff01; 就像去年看了一个号主写的&#xff1a;研究生遍地都是! 放眼全国14亿人口&#xff0c;别说研究生了&#xff0c;本科生占比有多少? “蓝桥杯是我人生中得到…...

vue3。 Cannot use JSX unless the ‘–jsx’ flag is provided. ts(17004)

react用tsx或者jsx很常见&#xff0c;也有配套的配置 那如果是vue呢&#xff1f; 默认是没问题的&#xff0c;可是我用了jsdoc&#xff0c;并开启了checkjs&#xff0c;然后vscode就爆红了 谷歌&#xff0c;百度&#xff0c;一个晚上 查到的答案&#xff1a; 推荐我新增tsco…...

HVV面试题目总结

蓝队 如何识别安全设备中的无效告警? 常见的端口有哪些? 这些端口对应的服务是什么? 针对这些服务&#xff0c;红队攻击方式有哪些? 常用的威胁情报平台有哪些? 有没有做过关于情报输出的工作? 木马驻留系统的方式有哪些? 当收到钓鱼邮件的时候&#xff0c;说说处置思路…...

Access denied for user ‘root‘@‘localhost‘ (using password:YES) 解决方案

文章目录 问题描述解决方案&#xff1a; 问题描述 Access denied for user ‘root’‘localhost’:拒绝用户’root’localhost’的访问。 出现这个报错语句的一般原因是输入了错误的密码&#xff0c;也有可能是是root帐户默认不开放远程访问权限。 相关的解决方法是重新设置…...

为什么C++这么复杂还不被淘汰?

C是一门广泛使用的编程语言&#xff0c;主要用于系统和应用程序的开发。尽管C具有一些复杂的语法和概念&#xff0c;但它仍然是编程界的重量级选手&#xff0c;在编程语言排行榜中一直位居前列。为什么C这么复杂还不被淘汰呢&#xff1f; C有以下优势 1、C具有高性能 C是一门编…...

内存泄漏的原因,内存泄漏如何避免?内存泄漏如何定位?

1. 内存溢出 内存溢出 OOM &#xff08;out of memory&#xff09;&#xff0c;是指程序在申请内存时&#xff0c;没有足够的内存空间供其使用&#xff0c;出现out of memory&#xff1b;比如申请了一个int,但给它存了long才能存下的数&#xff0c;那就是内存溢出。 2. 内存泄…...

关于全志T113开发板接7寸LCD屏幕显示异常问题的解决方案

在入手全志T113之后&#xff0c;第一时间移植好了之前6ull平台的rootfs。但是在测试QT的过程中发现屏幕最右侧有一部分显示不正常&#xff0c;经过初步推测应该是RGB行场同步时序有问题。本以为在设备树里面稍作修改之后就能OK&#xff0c;但是居然前前后后一共花了至少三个星期…...

SpringMVC第四阶段:Controller中如何接收请求参数

Controller中如何接收请求参数 1、原生API参数类型 1.1、HttpServletRequest类 只需要在Controller的目标方法中, 直接写上HttpServletRequest对象即可获取 原生API的 request对象实例。 RequestMapping(value "/p1") public String param1(HttpServletRequest …...

第三十回: LisvtView响应事件

我们在上一章回中介绍了如何给ListView添加分隔线,本章回中将介绍ListView响应事件相关的知识.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们在这里说的ListView响应事件主要分两种类型&#xff1a; 一种是滑动ListView时ListView做出响应&#xff0c;我们…...

重磅!用友荣登全球5强

近日&#xff0c;全球权威信息技术研究和顾问公司Gartner发布《Market Share: All Software Markets, Worldwide&#xff0c;2022》报告&#xff0c;用友在EAM&#xff08;资产管理&#xff09;市场再创新高&#xff0c;市场占有率位居全球第五位&#xff0c;亚太第一位&#x…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型

在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重&#xff0c;适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解&#xff0c;并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...

Linux-进程间的通信

1、IPC&#xff1a; Inter Process Communication&#xff08;进程间通信&#xff09;&#xff1a; 由于每个进程在操作系统中有独立的地址空间&#xff0c;它们不能像线程那样直接访问彼此的内存&#xff0c;所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...

RushDB开源程序 是现代应用程序和 AI 的即时数据库。建立在 Neo4j 之上

一、软件介绍 文末提供程序和源码下载 RushDB 改变了您处理图形数据的方式 — 不需要 Schema&#xff0c;不需要复杂的查询&#xff0c;只需推送数据即可。 二、Key Features ✨ 主要特点 Instant Setup: Be productive in seconds, not days 即时设置 &#xff1a;在几秒钟…...

二维数组 行列混淆区分 js

二维数组定义 行 row&#xff1a;是“横着的一整行” 列 column&#xff1a;是“竖着的一整列” 在 JavaScript 里访问二维数组 grid[i][j] 表示 第i行第j列的元素 let grid [[1, 2, 3], // 第0行[4, 5, 6], // 第1行[7, 8, 9] // 第2行 ];// grid[i][j] 表示 第i行第j列的…...

开源 vGPU 方案:HAMi,实现细粒度 GPU 切分

本文主要分享一个开源的 GPU 虚拟化方案&#xff1a;HAMi&#xff0c;包括如何安装、配置以及使用。 相比于上一篇分享的 TimeSlicing 方案&#xff0c;HAMi 除了 GPU 共享之外还可以实现 GPU core、memory 得限制&#xff0c;保证共享同一 GPU 的各个 Pod 都能拿到足够的资源。…...