【C++】类与对象(二)
前言
在前一章时我们已经介绍了类与对象的基本知识,包括类的概念与定义,以及类的访问限定符,类的实例化,类的大小的计算,以及C语言必须传递的this指针(C++中不需要我们传递,编译器自动帮我们实现)
但是仅仅只有这些还是不够的,类是面向对象编程语言的重中之重,对于它的理解我们应该继续深入,下面介绍类中的类中的6个默认成员函数中的前三个。
类与对象 二
- 一、类的6个默认成员函数
- 二、构造函数
- 1、 引入
- 2、概念
- 3、特性
- 三、析构函数
- 1、概念
- 2、特性
- 四、拷贝构造函数
- 1、概念
- a.为什么需要拷贝构造?
- 2、特征
- 3.拷贝构造函数典型调用场景
- 五、结语
一、类的6个默认成员函数
如果一个类中什么成员都没有,简称为空类。
空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。
默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。
空类:
class Date
{};
二、构造函数
1、 引入
对于构造函数的使用场景我们先来看一段简单都代码:
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef int DataType;
class Stack
{
public:void Init(int _capacity = 4)//缺省参数{DataType* tmp = (DataType*)malloc(sizeof(DataType) * _capacity);if (nullptr == tmp){perror("malloc fail:");exit(-1);}_a = tmp;_Top = 0;_capacity = _capacity;}void Push(int num){//判断是否应该扩容if (_Top - 1 == _capacity){_capacity *= 2;DataType* tmp = (DataType*)realloc(_a,sizeof(DataType) * _capacity);if (nullptr == tmp){perror("malloc fail:");exit(-1);}_a = tmp;}_a[_Top] = num;_Top++;}
private:DataType* _a;int _Top;int _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);return 0;
}
运行之后崩了,思考为什么?
答案是:我们没有进行初始化我们的栈,我们没有给空间,自然而然就无法插入数据了!这是很正常的,对于这样没有初始化然后崩溃的例子有很多,我们每次都要使用栈时都要进行初始化,这让我们很不舒服,可不可以当我们创建对象时自动帮我们进行初始化呢?答案是可以的,那便是构造函数!
2、概念
构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。
3、特性
构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。
其特征如下:
- 函数名与类名相同。
- 无返回值并且不允许我们写返回值。
- 对象实例化时编译器自动调用对应的构造函数。
- 构造函数可以重载。
- 如果类中没有显式定义构造函数(大白话:自己写构造函数),则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
前面我们说了,当我们在类中在什么都不写时编译器会自动帮我们生成构造函数,当然编译器自动生成的构造函数未必是我们想要的,我们也可以自己写构造函数,当我们自己写了构造函数,那编译器就不会再为我们生成构造函数了。
那么我们来改造一下上面的这个代码吧
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef int DataType;
class Stack
{
public:Stack(int capacity = 4)//缺省参数,此类构造函数可以传也可以不传递形参{DataType* tmp = (DataType*)malloc(sizeof(DataType) * capacity);if (nullptr == tmp){perror("malloc fail:");exit(-1);}_a = tmp;_Top = 0;_capacity = capacity;}void Push(int num){//判断是否应该扩容if (_Top - 1 == _capacity){_capacity *= 2;DataType* tmp = (DataType*)realloc(_a, sizeof(DataType) * _capacity);if (nullptr == tmp){perror("malloc fail:");exit(-1);}_a = tmp;}_a[_Top] = num;_Top++;}
private:DataType* _a;int _Top;int _capacity;
};
int main()
{Stack s1(20);//此处不是函数调用,而是类的实例化顺便给构造函数传参数//Stack s1; //如果是这样则会采用缺省值,即默认开辟4个int类型的空间大小。s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);s1.Push(5);s1.Push(6);s1.Push(7);return 0;
}
代码运行成功了,说明编译器自动帮我们调用了我们写的Stack
函数
我们再来看一个类的构造函数
#include<iostream>
using namespace std;
class Date
{
public:Date()//无参数的构造函数{}Date(int year, int month, int day)//函数重载{_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1();//报错,错误的调用无参构造函数,会被识别为函数声明!!!//warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)Date d2;//正确的调用无参构造函数Date d3(2023,2,10);//正确的调用必须传参的构造函数
};
注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
看完了需要传递参数的构造函数与不需要传递参数的构造函数,我们再来看看编译器自己实现的构造函数
//不写构造函数
#include<iostream>
using namespace std;
class Date
{
public:void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;d1.Print();return 0;
};
答案很奇怪啊!不是说当我们不写构造函数时,编译器会自己生成一个构造函数吗?并且构造函数的作用就是给对象一个合理的初始化值啊?打印的结果为什么是一个随机值呢?系统生成的构造函数好像没有什么用啊???
答案是:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int/char…,指针,自定义类型就是我们使用class/struct/union等自己定义的类型。对于编译器生成的默认构造函数有以下规则:
对于默认生成的构造函数:
- 内置类型的成员不做处理
- 对于自定义类型的成员,会去调用它的默认构造函数。
(默认构造函数包含了:全缺省的构造函数,不用传递参数的构造函数,以及系统默认生成的构造函数)
对于上面的类由于类中的成员全是内置类型,根据以上规则编译器生成的默认构造函数对内置类型不做处理,于是我们看到的还是随机值。
我们看下面一个代码帮助你理解此条规则
#include<iostream>
using namespace std;
class Time
{
public:Time(){cout << "Time()" << endl;_hour = 0;_minute = 0;_second = 0;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year;int _month;int _day;// 自定义类型Time _t;
};
int main()
{Date d;return 0;
}
看完这个例子相信你对这条规则以及有所了解了,但是我们还有一个问题?我们就想让内置类型与自定义类型一起初始化该怎么办呢?
6 .C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在类中声明时可以给默认值。(类似缺省参数)
#include<iostream>
using namespace std;
class Time
{
public:Time(){cout << "Time()" << endl;_hour = 0;_minute = 0;_second = 0;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year = 2023; //给默认值int _month = 2; //给默认值int _day = 1; //给默认值// 自定义类型Time _t;
};
int main()
{Date d;return 0;
}
7.无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。
class Date
{
public:
Date()
{
_year = 1900;
_month = 1;
_day = 1;
}
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
// 以下测试函数能通过编译吗?
int main()
{Date d1;return 0;
}
答案是不能,没有传递参数,函数不知道是应该调用无参的函数还是调用全缺省的函数
三、析构函数
1、概念
通过前面构造函数的学习,我们知道一个对象是怎么来的,那一个对象又是怎么没呢的?
析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。
2、特性
析构函数是特殊的成员函数,其特征如下:
- 析构函数名是在类名前加上字符 ~。
- 无参数无返回值类型。
- 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
- 对象生命周期结束时,C++编译系统系统自动调用析构函数。
实例代码:
#include<iostream>
using namespace std;
typedef int DataType;
class Stack
{
public:Stack(int capacity = 3){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = capacity;_size = 0;}void Push(DataType data){// CheckCapacity();_array[_size] = data;_size++;}// 析构函数~Stack(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}cout << "~Stack()" << endl;}
private:DataType* _array;int _capacity;int _size;
};
int main()
{Stack s;s.Push(1);s.Push(2);
}
5. 关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器生成的默认析构函数,对自定类型成员调用它的析构函数。
#include<iostream>
using namespace std;
class Time
{
public:~Time(){cout << "~Time()" << endl;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year = 1970;int _month = 1;int _day = 1;// 自定义类型Time _t;
};
int main()
{Date d;return 0;
}
程序运行结束后输出:~Time()
在main方法中根本没有直接创建Time类的对象,为什么最后会调用Time类的析构函数?
因为:main方法中创建了Date对象d,而d中包含4个成员变量,其中 _year, month, day三个是内置类型成员,销毁时不需要资源清理,最后系统直接将其内存回收即可;
而_t是Time类对象,所以在d销毁时,要将其内部包含的Time类的 _t 对象销毁,所以要调用Time类的析构函数。
但是:main函数中不能直接调用Time类的析构函数,实际要释放的是Date类对象,所以编译器会调用Date类的析构函数,而Date没有显式提供,则编译器会给Date类生成一个默认的析构函数,目的是在其内部调用Time类的析构函数,即当Date对象销毁时,要保证其内部每个自定义对象都可以正确销毁。
main函数中并没有直接调用Time类析构函数,而是显式调用编译器为Date类生成的默认析构函数。
注意:创建哪个类的对象则调用该类的析构函数,销毁那个类的对象则调用该类的析构函数
四、拷贝构造函数
1、概念
在我们使用类创建对象时,难免会发生拷贝行为,例如创建对象时,可否创建一个与已存在对象一某一样的新对象呢?
拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
a.为什么需要拷贝构造?
C/C++编译器拷贝变量时,并不是一件简单的事情,对于内置类型来说C/C++编译器可以自己拷贝(按照一个字节一个字节拷贝),对于自定义类型C/C++编译器不能进行拷贝,只有通过拷贝函数来进行拷贝。
(栈的拷贝要使用拷贝函数进行深拷贝!!!)
2、特征
拷贝构造函数也是特殊的成员函数,其特征如下:
- 拷贝构造函数是构造函数的一个重载形式。
//拷贝构造函数
#include<iostream>
using namespace std;
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}//Date(const Date d) // 错误写法:编译报错,会引发无穷递归Date(const Date& d) // 正确写法{_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;Date d2(d1);//利用拷贝构造创建一个与d1相同的d2//Date d2 = d1;//与上一行的意思一致,要调用拷贝构造return 0;
}
- 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
当我们想创建一个与d1相同数据的d2时要调用拷贝函数,
①调用拷贝函数要传递参数由于参数是形参,形参是实际参数的一份临时拷贝。
②于是我们又要调用拷贝函数,调用拷贝函数要传递参数由于参数是形参,形参是实际参数的一份临时拷贝。
③于是我们又又要调用拷贝函数,调用拷贝函数要传递参数由于参数是形参,形参是实际参数的一份临时拷贝。
④于是我们又又又要调用拷贝函数,调用拷贝函数要传递参数由于参数是形参,形参是实际参数的一份临时拷贝。
…
…
…
逻辑图:
还有一个问题就是拷贝构造的参数我们为什么要加const
呢?
答案是:怕我们拷贝反了!
3.若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
//默认生成的拷贝构造函数
#include<iostream>
using namespace std;
class Time
{
public:Time(){_hour = 1;_minute = 1;_second = 1;}Time(const Time& t){_hour = t._hour;_minute = t._minute;_second = t._second;cout << "Time::Time(const Time&)" << endl;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year = 1970;int _month = 1;int _day = 1;// 自定义类型Time _t;
};
int main()
{Date d1;// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构造函数Date d2(d1);return 0;
}
注意:在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定义类型是调用其拷贝构造函数完成拷贝的。
4.类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝。
思考一个问题:编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,对于内置类型我们还又必要写拷贝构造吗?答案是要不要写拷贝构造,我们还是要参考拷贝构造的特性4,有没有涉及支援申请!!!
我们看下面一段代码:
#include<iostream>
using namespace std;
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");return;}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);return 0;
}
上面的代码需要拷贝构造,不然两个栈会相互影响!可以看到拷贝构造的特性4就是我们写不写拷贝构造的依据!
3.拷贝构造函数典型调用场景
- 使用已存在对象创建新对象
- 函数参数类型为类类型对象
- 函数返回值类型为类类型对象
提醒:为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用尽量使用引用。
五、结语
本章的内容对于初学者来说挺难的,但是这些成员函数非常重要,务必要好好理解!学会它们后相信你的水平会有进一步提高!
相关文章:

【C++】类与对象(二)
前言 在前一章时我们已经介绍了类与对象的基本知识,包括类的概念与定义,以及类的访问限定符,类的实例化,类的大小的计算,以及C语言必须传递的this指针(C中不需要我们传递,编译器自动帮我们实现&…...

【软考】系统集成项目管理工程师(二十一)项目收尾管理
1. 项目验收2. 项目总结3. 系统维护4. 项目后评价补充:人员转移和资源遣散广义的系统集成项目收尾管理工作通常包含四类典型的工作:项目验收工作、项目总结工作、系统维护工作 以及 项目后评价工作,此外项目团队成员的后续工作也应在收尾管理时妥善安排;狭义的系统集成项目…...
关于公钥与私钥的一点看法
故事的起源 私密性 之前,用户a想给用户b发消息,a希望他自己发出现的消息,只能被b读懂。也就是说a希望发出去的数据是被加密过的,收到消息的人可以是b,c,d,e等等。但是只有b能被读懂。 这个需求…...

深入React源码揭开渲染更新流程的面纱
转前端一年半了,平时接触最多的框架就是React。在熟悉了其用法之后,避免不了想深入了解其实现原理,网上相关源码分析的文章挺多的,但是总感觉不如自己阅读理解来得深刻。于是话了几个周末去了解了一下常用的流程。也是通过这篇文章…...

32个关于FPGA的学习网站
语言类学习网站 1、HDLbits 网站地址:https://hdlbits.01xz.net/wiki/Main_Page 在线作答、编译的学习Verilog的网站,题目很多,内容丰富。非常适合初学Verilog的人!!! 2、牛客网 网站地址:http…...
5分钟快速上手Promise使用
promise 是处理异步编程的一种处理方式,可以将异步操作按照同步操作的方式编写。是一个对象或者构造函数,里面存放着某个未来才会执行的结果的方法(一般就是异步操作) 自己身上有all、reject、resolve这几个方法,原型上…...

大客户市场:阿里云、腾讯云、华为云“贴身肉搏”
配图来自Canva可画 近年来,随着中国逐渐进入数字化经济快车道,国内企业数字化、智能化升级已是刻不容缓。而为了帮助自身或其他企业实现数字化转型升级,阿里、腾讯、百度、京东、字节、网易、华为等众多国内知名企业早在多年以前,…...
华为OD机试 - 求字符串中所有整数的最小和(Python)| 真题+思路+代码
求字符串中所有整数的最小和 题目 说明 字符串 s,只包含 a-z A-Z + - ;合法的整数包括 1) 正整数 一个或者多个0-9组成,如 0 2 3 002 102 2)负整数 负号 - 开头,数字部分由一个或者多个0-9组成,如 -0 -012 -23 -00023输入 包含数字的字符串 输出 所有整数的最小和 …...

企业电子招投标采购系统源码之首页设计
功能模块: 待办消息,招标公告,中标公告,信息发布 描述: 全过程数字化采购管理,打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力,为…...

浅谈一下前端工作中全流程多层次的四款测试工具
在应届生找工作的时候,我们经常会见到一条招聘要求:要求实习经历。或者 有实习经历者优先。 为什么大部分公司在招聘时,都要求你必须有实习经历? 商业项目与个人项目不同,一段实习经历,能够熟悉公司中成熟…...

【运算放大器】反相放大电路仿真应用
目录 一、反相放大电路原理(简化电路) 二、反相放大电路电路原理(实际特性) 2.1原理图 2.2实际电路 三、虚短 虚断 3.1 虚短 3.2 虚断 四、作业 4.1 (反相)放大电路设计 4.2 LM741芯片 五、标准…...

数组的操作
1.splice 1.splice 是数组的一个方法,使用这个方法会改变原来的数组结构,splice(index ,howmany , itemX);这个方法接受三个参数,我们在使用的时候可根据自己的情况传递一个参数&…...

Python - 文件基础操作
目录 文件的读取 open()打开函数 read类型 read()方法 readlines()方法 readline()方法 for循环读取文件行 close() 关闭文件对象 with open 语法 文件的写入 文件的追加 文件的读取 操作 功能 文件对象 open(file, mode, encoding) 打开文件获得文件对象 文件…...

react的useState源码分析
前言 简单说下为什么React选择函数式组件,主要是class组件比较冗余、生命周期函数写法不友好,骚写法多,functional组件更符合React编程思想等等等。更具体的可以拜读dan大神的blog。其中Function components capture the rendered values这句…...

SharpImpersonation:一款基于令牌和Shellcode注入的用户模拟工具
关于SharpImpersonation SharpImpersonation是一款功能强大的用户模拟工具,该工具基于令牌机制和Shellcode注入技术实现其功能,可以帮助广大研究人员更好地对组织内部的网络环境和系统安全进行分析和测试。 该工具基于 Tokenvator的代码库实现其功能&a…...
华为OD机试 - 最大相连男生数(Python)| 真题+思路+代码
最大相连男生数 题目 学校组织活动,将学生排成一个矩形方阵。 请在矩形方阵中找到最大的位置相连的男生数量。 这个相连位置在一个直线上,方向可以是水平的、垂直的、成对角线的或者反对角线的。 注:学生个数不会超过 10000。 输入 输入的第一行为矩阵的行数和列数,接下…...

GIS在地质灾害危险性评估与灾后重建中的实践技术应用及python机器学习灾害易发性评价模型建立与优化
地质灾害是指全球地壳自然地质演化过程中,由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。由于降水、地震等自然作用下,地质灾害在世界范围内频繁发生。我国除滑坡灾害外,还包括崩塌、泥石流、地面沉…...

2.13、进程互斥的硬件实现方法
1、中断屏蔽方法 利用 “开/关中断指令” 实现(与原语的实现思想相同,即在某进程开始访问临界区到结束访问为止都不允许被中断,也就不能发生进程切换,因此也不可能发生两个同时访问临界区的情况) 优点:简单…...
Leetcode力扣秋招刷题路-2335
从0开始的秋招刷题路,记录下所刷每道题的题解,帮助自己回顾总结 2335. 装满杯子需要的最短总时长 现有一台饮水机,可以制备冷水、温水和热水。每秒钟,可以装满 2 杯 不同 类型的水或者 1 杯任意类型的水。 给你一个下标从 0 开…...
C语言深度解剖-关键字(6)
目录 1. 浮点型与零的比较: 1.1 推导: 1.2 实践: 总结: 理解强制类型转换: 指针与零比较 switch case 语句: 写在最后: 1. 浮点型与零的比较: 1.1 推导: 例&am…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...