C++类与对象(三)
目录
1.再谈构造函数
1.1 构造函数体赋值
1.2 初始化列表
1.3 explicit关键字
2.STATIC成员
2.1 概念
2.2 特性
3.C++中成员初始化的新玩法
4.友元
4.1 友元函数
4.2 友元类
5.内部类
6.再次理解封装
7.再次理解面向对象
本次内容大纲:
1.再谈构造函数
1.1 构造函数体赋值
在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。
class Date{public://构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;};
虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化, 构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值
class Date{public://构造函数Date(int year, int month, int day){_year = year; //第一次赋值_year = 2024; //第二次赋值//.....多次赋值_month = month;_day = day;}private:int _year;int _month;int _day;};
在函数体中,我们可以多次给成员对象赋值,而不是初始化
1.2 初始化列表
初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。
class Date
{
public:Date(int year, int month, int day)//初始化列表:_year(year),_month(month),_day(day){}
private:int _year;int _month;int _day;
};int main()
{Date d1(2024, 9, 15);return 0;
}
注意:
1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
2. 类中包含以下成员,必须放在初始化列表位置进行初始化:
- 引用成员变量
- const成员变量
- 自定义类型成员(且该类没有默认构造函数时)
引用成员变量和const成员变量都要一个相同的特点,在定义时必须初始化,所以它们只能使用初始化列表初始化
引用创建时必须初始化
int& a; //errorint b = 10;
int& a = b; //创建就初始化
const变量创建时必须初始化
const int a; //error 创建时未初始化const int a = 10; //创建时初始化
自定义成员:
若类中没有默认构造函数,我们实例化该类对象时应该传参对其初始化,即:初始化没有默认构造函数的类对象时,必须使用初始化列表来对其进行初始化
在这里说明一下,默认构造函数是指不用传参就可以调用的构造函数:
1.我们不写构造函数,编译器自己生成的
2.无参的构造函数
3.全缺省的构造函数
typedef int DateType;
class Stack
{
public://构造函数Stack(int capacity){_a = (DataType*)malloc(sizeof(DataType) * capacity);if(nullptr == _a){perror("Stack::malloc");exit(-1);}_top = 0;_capacity = capacity;}//析构函数~Stack(){if (_a){free(_a);_a = nullptr;_top = _capacity = 0;}}
private:int* _a;int _top;int _capacity;
};class A
{
public:A(int& ref, int a):_ref(ref),_a(a),_st(10){}
private:int& _ref; //引用const int _a = 2; //constStack _st; //没有默认构造函数
};int main()
{int p = 10;A a(p, 20);return 0;
}
在定义时就得初始化得变量类型,就必须放在初始化列表进行初始化
还有一个要注意得是,可以看到在构造函数的参数中其中ref引用的意义是防止野引用
如果这里是int ref的话,将一个局部变量给_ref初始化,就会导致_ref引用到一个被释放的空间
在类中声明时给值const int _a = 2;,这个意思是给初始化列表缺省值,如果我们没有在初始化列表对_a进操作,_a就会被赋值为2
3. 尽量使用初始化列表初始化
当你实例化一个对象时,初始化列表就是对象成员定义的地方,无论你是否使用初始化列表,每个对象成员都会走一遍初始化列表(成员变量需要定义出来)
对于内置类型,使用初始化列表和在构造函数体内初始化实际上没有什么区别,其差别就类似以下代码:
//使用初始化列表初始化
int a = 10;//使用函数体初始化(没有使用初始化列表)
int a;
a = 10;
对于自定义类型,使用初始化列表还可以提高代码效率
class Time
{
public:Time(int hour = 1){_hour = hour;}
private:int _hour;
};class test
{
public:test():_t(12) //调用拷贝构造函数{}
private:Time _t;
};
在类test中,我们调用了一次类Time中的构造函数
在不使用初始化列表的情况下:
class Time
{
public:Time(int hour = 1){_hour = hour;}
private:int _hour;
};class test
{
public:test(int hour){//初始化列表调用了一次构造函数(不使用初始化列表也会走这个流程)Time tmp(hour); //调用一次构造函数_t = tmp; //调用赋值运算符重载函数}
private:Time _t;
};
与上面那段代码对比,这里多调用一次构造函数和赋值运算符重载函数
初始化野不能解决我们百分之百的初始化问题
例如:
情况一:
typedef int DataType;class Stack
{
public://构造函数Stack(int capacity):_a((DataType*)malloc(sizeof(DataType)* capacity)), _top(0),_capacity(capacity){//我们需要_a做检查,初始化列表完成不了if(nullptr == _a){perror("Stack::malloc");exit(-1);}//我们还需要_a数组初始化一下,初始化初始化列表也完成不了memset(_a, 0, sizeof(int) * _capacity);}//析构函数~Stack(){if (_a){free(_a);_a = nullptr;_top = _capacity = 0;}}
private:DataType* _a;int _top;int _capacity;
};
情况二:
使用构造函数申请一个二维数组
class AA
{
public:AA(int row, int col):_row(row),_col(col){_a = (int**)malloc(sizeof(int*) * row);for (int i = 0; i < col; ++i){_a[i] = (int*)malloc(sizeof(int) * col);}}
private:int** _a;int _row;int _col;
};
初始化列表并不能帮我们完成初始化所有的事情
4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关
class A
{
public:A(int a):_a1(a), _a2(_a1){}void Print() {cout << _a1 << " " << _a2 << endl;}
private:int _a2;int _a1;
};//A.输出1 1
//B.程序崩溃
//C.编译不通过
//D.输出1 随机值
测试运行:
答案:D
1.3 explicit关键字
构造函数不仅可以初始化和赋值,对于单个参数的拷贝构造函数,还支持隐式类型转换
class A
{
public:A(int a):_a(a){cout << "A(int a)" << endl;}A(const A& aa):_a(aa._a){cout << "A(const A& aa)" << endl;}
private:int _a;
};int main()
{A a(1);A b = 2; //隐式类型转换,从内置类型到自定义类型return 0;
}
对于单个参数的拷贝构造函数,编译器是允许这样调用构造函数的,实际上这里还调用了一次拷贝构造函数
在语法上这里一段代码A b = 2;等价于下面两句代码:
A tmp(2); //调用构造函数
A b = tmp; //调用拷贝构造函数
先构造,在拷贝构造
早期的编译器就是这么处理的,当编译器遇到A b = 2;时它会先调用构造函数创建一个临时对象,然后讲这个临时对象拷贝构造给b。但是现在编译器已经做了优化,遇到A b = 2;时会按照A b(2);来进行处理,只会调用一次构造函数,这就是隐式类型转换
在我们仪以前的学习中,其实我们也遇到过隐式类型转换,例如:
int a = 10;
double b = a;
在这个过程中,为了保护a的值不被破环,会产生一个临时变量来存放a的值,然后将这个临时变量赋值给b
从汇编可以看到确实是这样操作的
但是,A b = 2;这种形式的可读性不是很好,所有我们可以使用explicit关键字来修饰构造函数,这样就可以禁止单参数构造函数的隐式类型转换
可以看到加入explicit之后就报错了
2.STATIC成员
2.1 概念
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的 成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化
2.2 特性
1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
例:
可以看到类中的静态变量不计入类大小,因为它存在于静态区,但是它属于类,属于这个类所有对象的成员
2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
class A
{
private:static int _a;
};int A::_a = 10;
单独一个类对象成员定义的地方是初始化列表,但是_a是静态成员变量,属于所有A类对象的成员,不是属于某一个对象的,所有它不能使用初始化列表,也不能给初始值,所以它是一个特例,不受访问限定符的影响,在全局域初始化
3. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
例:
class A
{
public:A(int p):_p(p){cout << "A()" << endl;}static void Print(){cout << _p << _a << endl;}
private:int _p;static int _a;
};int A::_a = 10;int main()
{A a(5);a.Print();return 0;
}
静态成员函数里面不能使用非静态成员
tips:
含有静态成员变量的类,一般含有一个静态成员函数,用于访问静态成员变量
4. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
(1)当静态成员变量公有时,有以下几种访问形式
class A
{
public:int _p;static int _a;
};int A::_a = 10;int main()
{A a;cout << a._a << endl; //使用类对象突破类域对静态成员进行访问cout << A()._a << endl; //使用匿名结构体突破类域对静态成员进行访问cout << A::_a << endl; //使用类名突破类域对静态成员进行访问
}
(2)当静态成员变量是私有时,有以下几种访问形式
class A
{
public:int _p;//没有this指针,指定类域和访问限定符就可以访问static int GetACount(){return _a;}
private:static int _a;
};int A::_a = 10;int main()
{A a;cout << a.GetACount() << endl; //通过对象调用静态成员函数来进行访问cout << A().GetACount() << endl; //通过匿名对象调用静态成员函数来进行访问cout << A::GetACount() << endl; //通过类名调用静态成员函数进行访问return 0;
}
这里说明一下:
使用非静态成员函数只能 得到_a的值,来使用它的值,并不能访问_a
class A
{
public:int _p;int GetACount(){return _a;}
private:static int _a;
};int A::_a = 10;int main()
{A a;cout << a.GetACount() << endl; //通过对象调用静态成员函数来得到_a的值return 0;
}
5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制
当静态成员是private时,尽管突破了类域也不能对其进行访问
【问题】
1. 静态成员函数可以调用非静态成员函数吗?
不可以,因为非静态成员函数第一个形参是this指针,而静态成员函数中没有this指针,所以静态函数成员不能调用非静态函数
2. 非静态成员函数可以调用类的静态成员函数吗?
可以,因为在类域中静态成员函数不受类域和访问限定符的限制
使用static情景:
设计一个类,只能在栈上创建对象
class A
{
public:static A GetStackObj(){A N1;return N1;}
private:A(){}
private:int _a;int _b;
};int main()
{A::GetStackObj();return 0;
}
3.C++中成员初始化的新玩法
C++11支持非静态成员变量在声明时进行初始化,但是要注意这里不是初始化,而是给初始化列表一个缺省值
class A
{
public:A(){}private://非静态成员声明时可以给缺省值int* _a = (int*)malloc(sizeof(int) * 10); int _b = 10;static int _c; //非静态对象不能直接给缺省值
};
初始化列表是你初始化定义的地方,如果你没有给值,那它就会使用你给的缺省值,如果你给了值,那么它就不会使用你的缺省值
我们学习了静态成员变量,现在我们来将他运用到题目中
例:
这是牛客上的一道题目,大家可以思考一下,使用静态变量怎么将这道题目写出来
class sum
{
public:sum(){_ret += _i;++_i;}static int GetACount(){return _ret;}
private:static int _ret;static int _i;
};int sum::_ret = 0;
int sum::_i = 1;class Solution
{
public:int Sum_Solution(int n) {sum a[n];return sum::_ret;}
};
4.友元
友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度(就是双方之间的亲密度),破坏了封装,所以友元不宜多用。
友元分为:友元函数和友元类
4.1 友元函数
问题:现在尝试去重载operator<<,然后发现没办法将operator重载成成员函数。因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以要将operator>>重载成成员函数但又会导致类外没办法访问成员,此时就需要友元来解决。operator>>同理。
我们知道在C++有一件很神奇的事,就是cout和cin可以自动识别输入和输出对象的类型,我们使用它们时不用像C语言一样增加输入输出的格式,这给我们提供了便利,难道C++真有这么神奇吗?其实不是,内置类型的变量可以直接使用cout和cin,是因为它们在库中已经实现了内置类型于运算符的重载
可以查看到,cout在ostream这个类中,而cin在istream这个类中
我们来实现一下自定义运算符的重载,让自定义类型也可以使用<<和>>
这里友元函数就起到作用了
class Date
{friend ostream& operator<<(ostream& _cout, const Date& d);friend istream& operator>> (istream& _cin, Date& d);
public:Date(int year = 1, int month = 1, int day = 1):_year(year),_month(month),_day(day){}private:int _year;int _month;int _day;
};ostream& operator<<(ostream& _cout, const Date& d)
{_cout << d._year << ' ' << d._month << ' ' << d._day;return _cout;
}istream& operator>>(istream& _cin, Date& d)
{_cin >> d._year >> d._month >> d._day;return _cin;
}int main()
{Date d1;cin >> d1;cout << d1;return 0;
}
这里上一节更详细大家有兴趣的可以去看看这里是链接 点击这里
注:
cout是ostream类中的一个全局对象,cin是istream类中的一个全局对象,<<和>>重载具有返回值,是为了连续的实现<<和>>的连续运算,它们的生命周期都是整个工程
说明:
友元函数可访问类的私有和保护成员,但不是类的成员函数
友元函数不能用const修饰
友元函数可以在类定义的任何地方声明,不受类访问限定符限制
一个函数可以是多个类的友元函数
友元函数的调用与普通函数的调用原理相同
4.2 友元类
声明友元类之后,Date中你所有成员函数都是Time中的友元函数,即:Date中的所有成员函数都可以访问Time中的私有成员
//友元类
class Time
{//声明Date是Time的友元类friend class Date;
public:Time(int hour = 1, int minute = 1, int second = 1):_hour(hour),_minute(minute),_second(second){}
private:int _hour;int _minute;int _second;
};class Date
{
public:Date(int year = 1, int month = 1, int day = 1):_year(year),_month(month),_day(day){}//使用Time类void SetTimeOFdate(int hour = 1, int minute = 1, int second = 1){T._hour = hour;T._minute = minute;T._second = second;}private:int _year;int _month;int _day;Time T;
};
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
- 友元关系是单向的,不具有交换性。
- 比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time 类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
- 友元关系不能传递 如果B是A的友元,C是B的友元,则不能说明C时A的友元。
- 友元关系不能继承,在继承位置再给大家详细介绍。
5.内部类
概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。
注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中 的所有成员。但是外部类不是内部类的友元。
特性:
1. 内部类可以定义在外部类的public、protected、private都是可以的。
2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
3. sizeof(外部类)=外部类,和内部类没有任何关系。
class A
{
private:static int _a;int _b;//B是A的内部类,B类是A类的天生友元class B{private:void foo(A& a){cout << a._b << endl;cout << _a << endl;}};
};
计算大小为:4
这里A的大小为4,内部类不算做整体的大小
学习了内部类,那么这道题目就可以使用内部类来完成
class Solution {class sum {public:sum() {_ret += _i;++_i;}};public:int Sum_Solution(int n) {sum a[n];return _ret;}static int _ret;static int _i;
};int Solution::_ret = 0;
int Solution::_i = 1;
6.再次理解封装
C++是一门面向对象的语言,面向对象编程语言具有三个特征:封装,继承,多态
C++通过类,将数据的属性和操作数据的方法封装在一起,进行结合就像去旅游一样,去参观一个景点,需要先预约买票,然后排队进入,进去之后只供观赏。若兵马俑可以让人随意的触摸,你一下我一下这些文物能保留多久呢?
所以我们去参观兵马俑时,他只允许我们观赏和拍照,并不允许我们做其他操作,这就是属于封装,通过将景点封装起来提供一个行为供我们使用。防止物品不让其他人破坏
博物馆管理系统
售票系统:负责将票卖给游客
工作人员: 检票,打扫,服务,安保,卫生等
导游:带领客户到指定位置参观博物馆,并且给客户讲解物品的缘由,历史等
通过对比理解,其实C++也是一样,将对象的属性和行为封装在一个类中,通过访问限定符,对类中的内容来进行管理,将用户需要的,我们能提供的设置为:public,为用户提供一个接口,至于其中实现的原理,用户就不需要知道,知道反而会增加使用或者维护的难度
7.再次理解面向对象
其实面向对象就是模拟抽象现实世界
相关文章:

C++类与对象(三)
目录 1.再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1.3 explicit关键字 2.STATIC成员 2.1 概念 2.2 特性 3.C中成员初始化的新玩法 4.友元 4.1 友元函数 4.2 友元类 5.内部类 6.再次理解封装 7.再次理解面向对象 本次内容大纲: 1.再谈构造函数 …...

云栖实录 | 阿里云 OpenLake 解决方案重磅发布:多模态数据统一纳管、引擎平权联合计算、数据共享统一读写
新一轮人工智能浪潮正在重塑世界,以生成式 AI 为代表的技术快速应用,推动了数据与智能的深化融合,同时也给数据基础设施带来了全新的变革与挑战。面向 AI 时代的数据基础设施如何构建?底层数据平台架构在 AI 时代如何演进…...

《线性代数》学渣笔记
文章目录 1 行列式1.1 克拉默法则1.2 基本性质1.3 余子式 M i j M_{ij} Mij1.4 代数余子式 A i j ( − 1 ) i j ⋅ M i j A_{ij} (-1)^{ij} \cdot M_{ij} Aij(−1)ij⋅Mij1.5 具体型行列式计算(化为基本型)1.5.1 主对角线行列式:主…...

对网页聊天项目进行性能测试, 使用JMeter对于基于WebSocket开发的webChat项目的聊天功能进行测试
登录功能 包括接口的设置和csv文件配置 这里csv文件就是使用xlsx保存数据, 然后在浏览器找个网址转成csv文件 注册功能 这里因为需要每次注册的账号不能相同, 所以用了时间函数来当用户名, 保证尽可能的给正确的注册数据, 时间函数使用方法如下 这里输入分钟, 秒…...

《程序猿之设计模式实战 · 适配器模式》
📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…...

Elasticsearch案例
目录 一、创建索引 二、准备数据 三、环境搭建 (1)环境搭建 (2)创建实体类 (3)实现Repository接口 四、实现自动补全功能 五、实现高亮搜索关键字功能 (1)在repository接口中…...

SpringBoot 项目如何使用 pageHelper 做分页处理 (含两种依赖方式)
分页是常见大型项目都需要的一个功能,PageHelper是一个非常流行的MyBatis分页插件,它支持多数据库分页,无需修改SQL语句即可实现分页功能。 本文在最后展示了两种依赖验证的结果。 文章目录 一、第一种依赖方式二、第二种依赖方式三、创建数…...

GSR关键词排名系统是针对谷歌seo的吗?
是的,GSR关键词排名系统专门针对谷歌SEO,具体通过外部优化手段快速提升关键词排名。不同于传统的SEO策略,GSR系统并不依赖于对网站内容的调整或内部优化,完全通过站外操作实现效果。这意味着,用户不需要花费精力在网站…...

HarmonyOS Next开发----使用XComponent自定义绘制
XComponent组件作为一种绘制组件,通常用于满足用户复杂的自定义绘制需求,其主要有两种类型"surface和component。对于surface类型可以将相关数据传入XComponent单独拥有的NativeWindow来渲染画面。 由于上层UI是采用arkTS开发,那么想要…...

什么是电商云手机?可以用来干什么?
随着电商行业的迅速发展,云手机作为一种创新工具正逐渐进入出海电商领域。专为外贸市场量身定制的出海电商云手机,已经成为许多外贸企业和出海电商卖家的必备。本文将详细介绍电商云手机是什么以及可以用来做什么。 与国内云手机偏向于游戏场景不同&…...

Python 2 和 Python 3的差异
Python 2 和 Python 3 之间有许多差异,Python 3 是 Python 语言的更新版本,目的是解决 Python 2 中的一些设计缺陷,并引入更现代的编程方式。以下是 Python 2 和 Python 3 之间的一些主要区别: 文章目录 1. print 语句2. 整除行为…...

Leetcode 第 139 场双周赛题解
Leetcode 第 139 场双周赛题解 Leetcode 第 139 场双周赛题解题目1:3285. 找到稳定山的下标思路代码复杂度分析 题目2:3286. 穿越网格图的安全路径思路代码复杂度分析 题目3:3287. 求出数组中最大序列值思路代码复杂度分析 题目4:…...

spring 注解 - @NotEmpty - 确保被注解的字段不为空,而且也不是空白(即不是空字符串、不是只包含空格的字符串)
NotEmpty 是 Bean Validation API 提供的注解之一,用于确保被注解的字段不为空。它检查字符串不仅不是 null,而且也不是空白(即不是空字符串、不是只包含空格的字符串)。 这个注解通常用在 Java 应用程序中,特别是在处…...

深入理解华为仓颉语言的数值类型
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在编程过程中,数据处理是开发者必须掌握的基本技能之一。无论是开发应用程序还是进行算法设计,了解不同数据类型的特性和用途都至关重要。本文将深入探讨华为仓颉语言中的基本数…...

WPF 的TreeView的TreeViewItem下动态生成TreeViewItem
树形结构仅部分需要动态生成TreeViewItem的可以参考本文。 xaml页面 <TreeView MinWidth"220" ><TreeViewItem Header"功能列表" ItemsSource"{Binding Functions}"><TreeViewItem.ItemTemplate><HierarchicalDataTempla…...

使用Go语言的互斥锁(Mutex)解决并发问题
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在并发编程中,由于存在竞争条件和数据竞争,我们需要将某些代码片段设定为临界区,并使用互斥锁(Mutex)等同步原语来保护这些临界区。本文将详细介绍Go语言标准库中Mutex的使用方法,以及如何利用它来解决实际…...

Android平台Unity3D下如何同时播放多路RTMP|RTSP流?
技术背景 好多开发者,提到希望在Unity的Android头显终端,播放2路以上RTMP或RTSP流,在设备性能一般的情况下,对Unity下的RTMP|RTSP播放器提出了更高的要求。实际上,我们在前几年发布Unity下直播播放模块的时候…...

网络:TCP协议-报头字段
个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》《C》《Linux》《网络》 文章目录 前言一、TCP协议格式16位源端口号 和 16位目的端口号4位首部长度16位窗口大小32位序号 和 32位确认序号6种标记位 和 16位紧急指针 总结 前言 本文是我对于TCP协…...

JAVA基础:HashMap底层数组容量控制,TreeMap底层存取机制,位运算符,原码反码补码
List常用实现类 List集合常用的实现类有3个 , ArrayList , LinkedList , Vector ArrayList 类似于我们之前的ArrayBox 底层使用数组存储元素, 插入删除的效率低,检索的效率高 当底层数组存储容量不足时,会进行扩容,…...

【Redis】Redis 缓存设计:抗住百万并发量的最佳实践
目录 1. Redis 缓存设计原则1.1 高可用性1.2 数据一致性1.3 读写分离 2. 缓存策略2.1 常用缓存策略2.1.1 缓存穿透2.1.2 缓存雪崩2.1.3 缓存击穿 2.2 额外缓存策略2.2.1 更新策略2.2.2 预热策略2.2.3 侧写缓存 3. Redis 架构设计3.1 单机 vs 集群3.2 Redis 集群示例架构 4. 性能…...

【hot100-java】【缺失的第一个正数】
R9-普通数组篇 class Solution {public int firstMissingPositive(int[] nums) {int nnums.length;for (int i0;i<n;i){while(nums[i]>0&&nums[i]<n&&nums[nums[i]-1]!nums[i]){//交换nums[i]和nums[nums[i]-1]int temp nums[nums[i]-1];nums[nums[i]…...

独立站新手教程转化篇:如何做好移动端优化?
随着移动设备在全球范围内的普及,越来越多消费者选择通过手机或平板电脑,来进行线上购物。因此移动端优化,因此移动端优化,也成为独立站卖家必须重视的一个关键环节。那么独立站移动端需要做好哪些优化工作呢? 选择响…...

Mybatis Plus分页查询返回total为0问题
Mybatis Plus分页查询返回total为0问题 一日,乌云密布,本人看着mybatis plus的官方文档,随手写了个分页查询,如下 Page<Question> questionPage questionService.page(new Page<>(current, size),questionService.g…...

VulnHub-Narak靶机笔记
Narak靶机笔记 概述 Narak是一台Vulnhub的靶机,其中有简单的tftp和webdav的利用,以及motd文件的一些知识 靶机地址: https://pan.baidu.com/s/1PbPrGJQHxsvGYrAN1k1New?pwda7kv 提取码: a7kv 当然你也可以去Vulnhub官网下载 一、nmap扫…...

查看和升级pytorch到指定版本
文章目录 查看和升级pytorch到指定版本查看pytorch的版本python 命令查看pytorch的版本使用pip 命令查看当前安装的PyTorch版本升级PyTorch到指定版本 升级到特定的版本 查看和升级pytorch到指定版本 查看pytorch的版本 python 命令查看pytorch的版本 通过Python的包管理工具…...

Maya---机械模型制作
材质效果(4)_哔哩哔哩_bilibili 三角面 四边面 多边面 *游戏允许出现三角面和四边面 游戏中一般是低模(几千个面) 动漫及影视是高模 机械由单独零件组合而成,需独立制作 低面模型到高面模型 卡线是为了将模型保…...

请不要在TS中使用Function类型
在 TypeScript 中,避免使用 Function 作为类型。Function 代表的是“任意类型的函数”,这会带来类型安全问题。对于绝大多数情况,你可能更希望明确地指定函数的参数和返回值类型。 如果你确实想表达一个可以接收任意数量参数并返回任意类型的…...

关于UVM仿真error数量达到指定值就退出仿真的设置
1. 问题描述 在某项目调试过程中,发现通过tc_base.sv中new函数里的set_report_max_quit_count()设置最大error数量不生效,uvm_error数量仍旧是达到10个(默认)就会退出仿真。 2. 设置uvm_error到达一定数量结束仿真的方式 由白皮…...

chatGPT问答知识合集【二】
Redis 架构说明 Redis 是一个开源的内存数据库,它也可以持久化到磁盘。以下是 Redis 的典型架构说明:### Redis 架构组件:1. **客户端**:与 Redis 服务器进行通信的应用程序或客户端库。2. **Redis 服务器**:执行实际…...

不靠学历,不拼年资,怎么才能月入2W?
之前统计局发布了《2023年城镇单位就业人员年平均工资情况》,2023年全国城镇非私营单位和私营单位就业人员年平均工资分别为120698元和68340元。也就是说在去年非私营单位就业人员平均月薪1W,而私营单位就业人员平均月薪只有5.7K左右。 图源:…...