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

c++重中之重:“换个龟壳继续套娃“:运算符重载等的学习

 

 

文章目录

  • 前言
  • 一.运算符重载
  • 二.const成员
  • 三.取地址重载
  • 总结

 


前言

上一期我们讲到类的6个默认构造函数中的拷贝构造函数,这一期我们继续往下讲,当然难点肯定是运算符重载了。


 

一、运算符重载

运算符重载是c++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数相似。

函数名字为:关键字operator后面接需要重载的运算符符号

函数原型:返回值类型operator操作符(参数列表)

注意:

1.不能通过连接其他符号来创建新的操作符。比如:operator@

2.重载操作符必须有一个类类型参数

3.用于内置类型的运算符,其含义不能改变。例:内置的整形 + ,不能改变+的含义,比如把加法弄成乘法之类的。

4.作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this。

5.有五个运算符是不能重载的。1 .*(点星) 2  ::(域名限定符)   3  sizeof    4  ?:(三目操作符) 5  . (成员访问操作符)

class Date
{
public:Date(int year = 10, int month = 10, int day = 10){_year = year;_month = month;_day = day;}void print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1(2023,2,10);Date d2(2023,2,5);d2.print();return 0;
}

 像上面的d1和d2两个参数该如何比较大小呢?以前在C语言我们通常写一个函数是传两个日期的地址过去然后挨个用指针访问去比较最后返回布尔值,这样会非常的麻烦,而c++的运算符重载正好解决了这个问题。:

class Date
{
public:Date(int year = 10, int month = 10, int day = 10){_year = year;_month = month;_day = day;}void print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}bool operator==(const Date& d){return _year == d._year&& _month == d._month&& _day == d._day;}
private:int _year;int _month;int _day;
};
int main()
{Date d1(2023,2,10);Date d2(2023,2,10);cout << (d1 == d2) << endl;return 0;
}

 b73573bb15e54fc49d16643fcf22e4a7.png

b23f10412c9b4eadb52588f6ed02512d.png 通过上面的代码和图片大家应该可以看到运算符重载对于自定义类型有多方便,而运算符重载的规则我们也讲过,那么写到类外什么样子呢?

(由于类外不可访问类内私有成员可以先将私有成员改为共用或者知道友元函数的用友元)

b0f8108e45284803a3b98a11cf9c946b.png

类外的区别就是多一个参数,因为在类内有this指针。 cout打印d1==d2加括号的原因是流插入操作符的优先级高于==。

符号>的重载:

bool operator>(const Date& d){if (_year > d._year){return true;}else if (_year == d._year && _month > d._month){return true;}else if (_year == d._year && _month == d._month && _day > d._day){return true;}else{return false;}}

 715e47c783f949e99cd1b2f37a308302.png

符号<=的重载:

bool operator<=(const Date& d){return !(*this > d);}

 我们可以发现运算符很多都是实现一两个其他的就可以复用了。小于等于不就是大于的取反吗,只需要知道类内函数有隐藏的参数this默认指向第一个操作数即可。

符号<:

bool operator<(const Date& d){return !(*this > d)&&!(*this==d);}

 小于就是大于等于的取反。

符号>=:

bool operator>=(const Date& d){return !(*this < d);}

 大于等于就是小于的取反。

符号!=:

bool operator!=(const Date& d){return !(*this == d);}

 赋值运算符重载

赋值运算符的重载格式:

1.参数类型 const T&,传递引用可以提高传参效率。

2.返回值类型T& ,返回引用可以提高返回的效率,有返回值的目的是为了实现连续赋值

3.检测自己给自己赋值(因为两个一样的变量再去赋值会消耗空间)

4.返回*this 要复合连续赋值的含义

注意:赋值运算符的重载并不是强制要求参数为&,这里要和拷贝构造区分,赋值运算符即使用传值调用也可以使用不会发生无穷调用因为在传自定义类型参数的时候先拷贝构造一个临时变量然后将这个变量赋值给变量即可。

Date& operator=(const Date& d){_year = d._year;_month = d._month;_day = d._day;return *this;}

 d4ddac9956ab4c6bb7c274895c74df25.png

 一般来说赋值给另一个对象是不需要返回值的,但是为了实现连续赋值那么就必须返回被赋值的那个变量,由于被赋值的对象不会被销毁,所以为了不调用拷贝构造函数浪费空间直接使用引用返回即可。如果有人写成d1= d1这样的代码,那么不就白白的浪费了空间吗,所以我们直接判断一下

Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}

this是左操作数的地址,&d是右操作数的地址,这样的好处就是即使赋值时出现操作数一样的情况也不会白白浪费空间。

注意:运算符的顺序不是从右往左也不是从左往右,这是要看操作符的结合性的。

比如: += 是从右往左开始的   + 是从左往右开始的

我们之前说过,类的6个默认函数即使我们不写编译器也会写一个默认的,那么默认的能完成赋值重载的任务吗?这个问题和拷贝赋值是一样的,对于内置类型编译器可以完成赋值,但是对于像栈那样需要开不同空间的必须我们手动去写一个赋值重载。

c03373ebfcbe484c9dceb7bddca036ef.png

 前面讲拷贝构造的时候忘记了一个细节,那就是向上图中红色框起来的也是拷贝构造,有些人会有疑问,这里不是用赋值重载了吗?其实并不是,赋值重载的调用是针对两个已经实例化好的或定义的对象,而像上图中d5还没有定义出来是在实例化的过程中,是用d1初始化d5,用一个对象初始化一个对象用的是拷贝构造。

下面我们利用运算符重载实现一个计算日期的小程序,小程序的功能包括:日期+天数,日期+=天数,日期-天数,日期-=天数,日期的前置++后置++,日期的前置--后置--,日期-日期相差多少天,下面先展示源代码然后我们一个函数一个函数讲解:

class Date
{
public:Date(int year = 2023, int month = 2, int day = 10){if (year > 0 && (month >= 1 && month <= 12) && (day > 0 && day <= GetMonthDay(year, month))){_year = year;_month = month;_day = day;}else{cout << "日期不合法:" << endl;exit(-1);}}void Print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}bool operator==(const Date& d){return _year == d._year&& _month == d._month&& _day == d._day;}bool operator<(const Date& d){if (_year < d._year){return true;}else if (_year == d._year && _month < d._month){return true;}else if (_year == d._year && _month == d._month && _day < d._day){return true;}else{return false;}}bool operator>=(const Date& d){return !(*this < d);}bool operator>(const Date& d){return !(*this < d) && !(*this == d);}bool operator<=(const Date& d){return !(*this > d);}bool operator!=(const Date& d){return !(*this == d);}Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}int GetMonthDay(int year, int month){int MonthArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)){return 29;}else{return MonthArray[month];}}//日期 += 天数Date& operator+=(int day){if (day < 0){*this -= -day;return *this;}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month == 13){_year++;_month = 1;}}return *this;}//日期 + 天数Date operator+(int day){Date tmp(*this);tmp += day;return tmp;}//前置++Date& operator++(){*this += 1;return *this;}//后置++Date operator++(int){Date tmp(*this);*this += 1;return tmp;}//日期 -= 天数Date& operator-=(int day){if (day < 0){*this += -day;return *this;}_day -= day;while (_day <= 0){_month--;if (_month == 0){_year--;_month = 12;}_day += GetMonthDay(_year, _month);}return *this;}//日期 - 天数Date operator-(int day){Date tmp(*this);tmp -= day;return tmp;}//前置--Date& operator--(){*this -= 1;return *this;}//后置--//int参数 仅仅是为了占位,根前置重载区分Date operator--(int){Date tmp(*this);*this -= 1;return tmp;}//日期相减(得到的是天数)int operator-(const Date& d){Date Max = *this;Date Min = d;int flag = -1;if (*this < d){Max = d;Min = *this;flag = 1;}int n = 0;while (Max != Min){n++;Min++;}return n * flag;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2023, 12, 3);Date d2(2023, 6, 4);//cout << (d1 > d2) << endl;/*d1 = --d2;d1.Print();d2.Print();*///d2.Print();//cout << (d1 - d2) << endl;d2 =d1 - -100;d2.Print();return 0;
}

 首先,我们在构造函数中初始化的时候要确保日期是合法的,不能出现月数小于0或者大于12的,并且天数要大于0小于当月最大天数,所以我们在构造函数中加了一个判断,当日期不合法时就输出"日期不合法"并且退出程序。

int GetMonthDay(int year, int month){int MonthArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)){return 29;}else{return MonthArray[month];}}

因为我们计算日期的时候必须知道每个月是多少天而且还有闰年二月是29天的情况,所以我们写了一个函数得到每个月的天数,数组有13个是因为数组是从0开始我们为了方便直接在第一个位置加一个0即可。

接下来我们讲解日期+=天数:

Date& operator+=(int day){if (day < 0){*this -= -day;return *this;}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month == 13){_year++;_month = 1;}}return *this;}

 f200449ddde44486beb7fbb5166b9385.png

在这里由于不确定要加多少天如果加1000天那么就要重复上图的步骤所以这是一个循环,当天数大于当月最大天数的时候就进入循环,需要注意的是当月数加到13就说明越界了要及时改为合法月数。因为+=就是会改变本身的值,并且在函数结束后日期也没有被销毁,所以我们采用传引用的方式减少拷贝构造的消耗。判断天数是否小于0是因为我们不知道有人会不会写成-数,如果是负数那就是-=一个正数。

Date operator+(int day){Date tmp(*this);tmp += day;return tmp;}

 日期+天数那么是不会改变本身的,所以我们需要拷贝构造一个变量,这时候直接复用+=操作符即可,由于tmp是函数中的临时变量,函数结束就会销毁,所以不能采用传引用的方式。

//前置++Date& operator++(){*this += 1;return *this;}

 前置++是先++在使用,所以直接+1返回即可。

//后置++Date operator++(int){Date tmp(*this);*this += 1;return tmp;}

 后置++是先使用再++,也就是说我们必须用一个变量接收开始的日期,然后自己+1返回开始没有+1的那个值即可,由于这个值是临时变量所以只能用传值返回。需要注意的是,编译器区分前置++和后置++的点是后置++的参数有一个int,这个int是占位符没有实际作用,也不用写参数,写一个int即可。

//日期 -= 天数Date& operator-=(int day){if (day < 0){*this += -day;return *this;}_day -= day;while (_day <= 0){_month--;if (_month == 0){_year--;_month = 12;}_day += GetMonthDay(_year, _month);}return *this;}

01633d9128e8403fa9ffeef207135c42.png  

 需要注意的是减去天数后如果大于0就说明本月的天数够用不需要向上个月借,等于0也需要借因为没有2月0日,为了让借到的天数是上个月的所以月份--后再加上借的天数,与+=同理都要判断day是否为负数,为负数就变成了+上一个正数,那为什么+和-我们没有判断呢?因为+和-我们是用+=和-=复用的。

//日期 - 天数Date operator-(int day){Date tmp(*this);tmp -= day;return tmp;}

 这里与+一样复用就可以。前置--和后置--也与++一样。

//日期相减(得到的是天数)int operator-(const Date& d){Date Max = *this;Date Min = d;int flag = -1;if (*this < d){Max = d;Min = *this;flag = 1;}int n = 0;while (Max != Min){n++;Min++;}return n * flag;}

日期相减实现起来也很简单,我们以之前的为负,以后的为正,先定义两个变量Max和Min来存放两个日期,我们默认是第一个日期大于第二个日期,当第一个大于第二个日期的时候就说明是之前的那么让flag为负,如果第一个日期小于第二个日期,就让flag为正。然后我们用n来记录天数,当两个日期不相等就进入循环,让n和小的那个日期自加直到相等我们就能计算出有多少天了。

那么我们每次调用函数去打印日期是不是不方便呢?能不能直接用cout打印日期呢?答案是可以的,我们通过重载<<运算符即可完成。我们现在类中声明然后再类外实现。

6064ae0d669b4323a5d7e71a647448af.png 

那么我们写了一个为什么不能调用呢? b6e62ec09ff04e9cba9f808ba157052b.png

 我们只能通过调用函数的方式去调用,和我们想的并不一样,这怎么办呢?我们用cout不能直接调用的原因是操作符的左边是左操作数,右边是右操作数,而我们常用的打印习惯是右操作数,那么我们先来看一下左操作数是否能正确调用:

bcacee1a61bb4101aedb277509e15eb4.png

 我们发现是可以正确调用的,但是很奇怪我们喜欢写到右边。解决这个问题之前我们要先知道运算符重载在类中第一个操作符是*this,而像我们那样的写法很明显out是右操作数了,我们要的是out去作为左操作数,想要让out成为左操作数将运算符重载写到外面了不就解决了吗,因为外面是没有*this的。

b60aab9d83c04ebc80596f723c580eb7.png

但是当我们写到定义在类外发现不能访问类内的成员了,这里的解决方式有多个,我们讲两个简单的即可,第一个将类内私有改为公有如下图:

9a47ed1037e541b78940a6b8ee0b30a3.png

第二个是用友元函数,我们将这个函数设为类的友元就可以访问类的所有成员了。

6e43dddbc8af4e16b51f36bd7a1783ca.png aff0748b87b9484194e6bbd1729be082.png

 f46b26264e5544a0ade02787822004b5.png

 为什么编译器的cout支持多个打印我们的不可以呢?这是因为我们没有返回值,我们应该要将out返回这样就能连续打印了,因为out出了作用域没有被销毁所以我们可以返回其引用。

09ae26e18ef54f48be4b891a56e38ae9.png 4c2c15e2291d46de8afbb4d631300e10.png

这样就解决了打印自定义类型的问题,接下来我们再重载一下cin,与cout一样只需要改一下参数即可。

49601924b86143b88bff80e7463e976a.png

5ee6ff12334b495a95d9160a666f6aa9.png 为什么输入的参数d我们不加const了呢?这是因为我们输入会改变const的值如果加了const就不能改变了。

在这里需要注意一下,类里面的短小函数,适合做内联的函数,直接是在类里面定义的。

const成员

将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

class A
{
public:void Print(){cout << _a << endl;}
private:int _a;
};
int main()
{/*A aa;aa.Print();*/const A aa; //权限的放大aa.Print();return 0;
}

419325d00e9741ea89b0be8ef9ccea3a.png

在这里为什么会报错呢?因为aa的类型是const A* ,而传递给this指针后变成了A* ,所以这里是权限的放大,想要解决只需要给this指针也用const修饰,如下图:

ac6188a4b63441909d9c44a91bebe1e8.png

这里函数后面的const修饰的是this指针,让this指针变成了const A*。

1c65ac6bc2db4be3a0000be3e684a9ca.png而上图是权限的缩小,权限的缩小是没有问题的,调用Func函数从A*变成了const A*.

总结:内部不改变成员变量的成员函数,最好加上const,const对象和普通对象都可以调用,比如下面的代码:

#include <assert.h>
class Array
{
public:int& operator[](int i){assert(i < 10);return _a[i];}const int& operator[](int i) const{assert(i < 10);return _a[i];}private:int _a[10];int _size;
};
void Func(const Array& d)
{for (int i = 0; i < 10; i++){cout << d[i] << " ";}
}
int main()
{Array ay;for (int i = 0; i < 10; i++){ay[i] = i * 10;}for (int i = 0; i < 10; i++){cout << ay[i] << " ";}Func(ay);return 0;
}

取地址重载

取地址重载和赋值运算符重载一样都会由编译器自己生成,当然有需求也可以自己去写。

939165b7ce584f3c9f632f1309239443.png

本来自定义类型用运算符必须自己重载,但是赋值运算符和取地址重载编译器生成的就够用。

9d550cff008d408e805821ecead76595.png 当然如果我们不想让别人获取我们的地址我可可以返回一个假地址如上图所示

0a454e68b5bd492cb93fad09dc768b7d.png

以上就是取地址重载的用法,总之不是非常必要是不用去自己写取地址重载和const取地址重载的。 

 


总结

学会运算符重载是学习c++必备的技能,c++独特的就是自定义类型,而运算符重载可以解决自定义类型使用运算符的问题。

 

相关文章:

c++重中之重:“换个龟壳继续套娃“:运算符重载等的学习

文章目录 前言一.运算符重载二.const成员三.取地址重载总结前言 上一期我们讲到类的6个默认构造函数中的拷贝构造函数&#xff0c;这一期我们继续往下讲&#xff0c;当然难点肯定是运算符重载了。 一、运算符重载 运算符重载是c为了增强代码的可读性引入了运算符重载&#xf…...

RabbitMQ简单使用

这篇文章通过一个最简单的例子&#xff0c;让初学者能了解RabbitMQ如何完成生产消息和消息的。 所有的程序员在学习一门新技术的时候&#xff0c;都是从 Hello World 进入到Colorful World的&#xff0c;本节也将按照惯例&#xff0c;从HelloWorld开始&#xff0c;演示RabbitMQ…...

Lambda表达式

&#x1f44c; 棒棒有言&#xff1a;也许我一直照着别人的方向飞&#xff0c;可是这次&#xff0c;我想要用我的方式飞翔一次&#xff01;人生&#xff0c;既要淡&#xff0c;又要有味。凡事不必太在意&#xff0c;一切随缘&#xff0c;缘深多聚聚&#xff0c;缘浅随它去。凡事…...

JSON数据格式【学习记录】

JSON介绍 JSON&#xff08;JavaScript Objet Notation&#xff09;是一种轻量级的数据交换格式。它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。它采用一种键:值对的文本格式来存储和表示数据&#xff0c;在系统交换数据过程中常常被使用&#xff0c;是…...

LeetCode——1234. 替换子串得到平衡字符串

一、题目 有一个只含有 ‘Q’, ‘W’, ‘E’, ‘R’ 四种字符&#xff0c;且长度为 n 的字符串。 假如在该字符串中&#xff0c;这四个字符都恰好出现 n/4 次&#xff0c;那么它就是一个「平衡字符串」。 给你一个这样的字符串 s&#xff0c;请通过「替换一个子串」的方式&a…...

Web自动化测试——selenium篇(二)

文章目录一、浏览器相关操作二、键盘操作三、鼠标操作四、弹窗操作五、下拉框选择六、文件上传七、错误截图一、浏览器相关操作 浏览器窗口大小设置 driver.manage().window().maximize();//窗口最大化 driver.manage().window().minimize();//窗口最小化 driver.manage().wi…...

RK3399平台开发系列讲解(文件系统篇)虚拟文件系统的数据结构

🚀返回专栏总目录 文章目录 一、超级块二、挂载描述符三、文件系统类型四、索引节点五、目录项沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍虚拟文件系统的数据结构。 一、超级块 文件系统的第一块是超级块,用来描述文件系统的总体信息。当我们把文件系…...

企业财务管理升级,智慧税务和数据可视化打造新标准

一、引言在发展社会主义市场经济的过程中&#xff0c;税收承担着组织财政收入、调控经济、调节社会分配的职能。中国每年财政收入的90%以上来自税收&#xff0c;其地位和作用越来越重要&#xff0c;可称之为国家经济的“晴雨表”&#xff0c;有效进行税务管理、充分挖掘税务大数…...

JFET(结型场效应管)

JFET的结构示意图 参考&#xff1a;https://blog.csdn.net/weixin_45882303/article/details/106008695 下图是实际结构图&#xff0c; 下面是原理图和符号表示&#xff08;参考连接中的图片&#xff09; 分析 VGS 对电压id的控制&#xff08;固定VDS&#xff09; 当让D和…...

oceanbase部署--使用OBD部署obagent和promethous_grafana软件

obagent OBAgent 通常部署在 OBServer 节点上。OBAgent支持推、拉两种数据采集模式&#xff0c;可以满足不同的应用场景。 OBAgent默认支持的插件包括主机数据采集、OceanBase 数据库指标的采集、监控数据标签处理和 Prometheus 协议的 HTTP 服务。 1&#xff09;编辑 OBAgent …...

浏览器广告拦截插件| 浏览器搜索广告横飞怎么办

文章目录浏览器广告拦截插件| 浏览器搜索广告横飞怎么办一、效果二、安装浏览器广告拦截插件| 浏览器搜索广告横飞怎么办 浏览器广告横飞怎么办&#xff1f;今天教你一招解决&#xff01;很多小伙伴说自己用的浏览器总是有广告。 今天咱们就针对这个问题分享一个浏览器插件&a…...

Redis优化内存篇

【内存消耗】 场景&#xff1a;业务ID->图片ID&#xff08;KV:partnerId->objectId&#xff09;。 刚开始&#xff0c;我们保存了1亿张图片&#xff0c;大约用了6.4GB的内存。 随着图片数据量的不断增加&#xff0c;Redis变慢了。 新的认知&#xff1a;String类型并不是适…...

Vue原理解析

文章目录1. VUE的响应式原理1.1 ViewModel1.2 双向绑定的基本原理1.3 什么是响应性1.4 Vue 中的响应性是如何工作的2. Vue 渲染机制2.1 虚拟 DOM2.2 渲染管线2.3 带编译时信息的虚拟 DOM2.3.1 静态提升2.3.2 修补标记 Flags2.3.3 树结构打平2.3.4 对 SSR 激活的影响1. VUE的响应…...

C# Lambda表达式含义及各种写法

Lambda表达式在各个语言中的表达方式都不太相同&#xff0c;本文重点介绍C#的Lambda表达式。 首先&#xff0c;Lambda表达式就是一个匿名的方法/函数。 以下面的一个完整版作为例子&#xff0c;前面是参数&#xff0c;后面是返回值&#xff1a; 由于 Lambda表达式和委托常常一起…...

计算机组成原理:1. 计算机系统概论

更好的阅读体验\huge{\color{red}{更好的阅读体验}}更好的阅读体验 文章目录1.1 计算机系统简介1.1.1 计算机软硬件概念1.1.2 计算机的层次1.1.3计算机组成和计算机体系结构1.2 计算机的基本组成1.2.1 冯诺伊曼计算机的特点1.2.2 计算机的硬件框图1.2.3 计算机的工作步骤1.3 计…...

【c#】c#常用小技巧方法整理(5)—— 字符串操作类

1、GetStrArray(string str, char speater, bool toLower) 把字符串按照分隔符转换成 List 2、GetStrArray(string str) 把字符串转 按照, 分割 换为数据 3、GetArrayStr(List list, string speater) 把 List 按照分隔符组装成 string 4、GetArrayStr(List list) 得到数组列表以…...

用队列实现栈VS用栈实现队列

之前我们就讲过队列&#xff0c;栈的基础知识&#xff0c;笔者之前有过详细的介绍&#xff0c;感兴趣的可以根据笔者的个人主页进行查找&#xff1a;https://blog.csdn.net/weixin_64308540/?typelately225. 用队列实现栈请你仅使用两个队列实现一个后入先出&#xff08;LIFO&…...

MY2480-16P语音模块的使用

MY2480-16P语音模块的使用开发环境&#xff1a;STM32CUBEMXKEIL5辅助软件&#xff1a;串口助手、迅捷文字转语音一、MY2480-16P语音模块引脚图及引脚定义二、选择触发方式三、使用串口控制MY2480-16P语音模块四、模块使用指南开发环境&#xff1a;STM32CUBEMXKEIL5 辅助软件&a…...

I/O 多路复用

。新到来一个 TCP 连接&#xff0c;就需要分配一个进程或者线程&#xff0c;那么如果要达到 C10K&#xff0c;意味着要一台机器维护 1 万个连接&#xff0c;相当于要维护 1 万个进程/线程&#xff0c;操作系统就算死扛也是扛不住的。 一个进程虽然任一时刻只能处理一个请求&…...

2023 最新版网络安全保姆级指南,从0到1,建议收藏!

一、网络安全学习的误区 1.不要试图以编程为基础去学习网络安全 不要以编程为基础再开始学习网络安全&#xff0c;一般来说&#xff0c;学习编程不但学习周期长&#xff0c;且过渡到网络安全用到编程的用到的编程的关键点不多。一般人如果想要把编程学好再开始学习网络安全往…...

力扣39.组合总数

文章目录力扣39.组合总数题目描述方法1&#xff1a;深搜回溯力扣39.组合总数 题目描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可…...

sql的case when用法详解

简单CASE WHEN函数&#xff1a; CASE SCORE WHEN A THEN 优 ELSE 不及格 END CASE SCORE WHEN B THEN 良 ELSE 不及格 END CASE SCORE WHEN C THEN 中 ELSE 不及格 END等同于&#xff0c;使用CASE WHEN条件表达式函数实现&#xff1a; CASE WHEN SCORE A THEN 优WHEN SCORE …...

AtCoder Grand Contest 061(题解)

A - Long Shuffle 这道题本质是一个找规律的题 既然是打表题&#xff0c;我们先暴力把他打出来 (盗一张图.jpg) 接下来就是在这张图中挖掘答案 我们可以明显的看到偶数行是有一些规律的 要么是相邻对的互换&#xff0c;要么不变 不变和互换的位置也有讲究&#xff0c;在二进制…...

生成系列论文:文本控制的3d点云生成 TextCraft(一):论文概览

TextCraft: Zero-Shot Generation of High-Fidelity and Diverse Shapes from Text 论文原文&#xff1a; https://arxiv.org/abs/2211.01427 论文的研究动机 DALL2已经在文本控制的图像生成上取得很好的效果&#xff0c;但是基于文本控制的3d点云生成的研究还不太成熟&#…...

IDEA常用插件

常用IDEA插件 Codota 插件下载地址&#xff1a;Codota AI Autocomplete for Java and JavaScript - IntelliJ IDEs Plugin | Marketplace IDEA的自动补全功能已经很强大了&#xff0c;但是这个插件的自动补全功能更加强大&#xff0c;这是一个基于AI技术&#xff0c;学习了大量…...

Spring的事务传播机制

多个事务方法相互调用时&#xff0c;事务如何在这些方法之间进行传播&#xff0c;Spring中提供了七种不同的传播机制&#xff0c;来保证事务的正常执行&#xff1a; REQUIRED&#xff1a;默认的传播机制&#xff0c;如果存在事务&#xff0c;则支持/加入当前事务&#xff0c;如…...

Python:路径之谜(DFS剪枝)

题目描述 小张冒充 X 星球的骑士&#xff0c;进入了一个奇怪的城堡。 城堡里边什么都没有&#xff0c;只有方形石头铺成的地面。 假设城堡地面是 nn 个方格。如下图所示。 按习俗&#xff0c;骑士要从西北角走到东南角。可以横向或纵向移动&#xff0c;但不能斜着走&#xf…...

阿里巴巴在开源压测工具 JMeter 上的实践和优化

Apache JMeter [1] 是 Apach 旗下的开源压测工具&#xff0c;创建于 1999 年初&#xff0c;迄今已有超过 20 年历史。JMeter 功能丰富&#xff0c;社区&#xff08;用户群体&#xff09;庞大&#xff0c;是主流开源压测工具之一。 性能测试通常集中在新系统上线或大型活动前&…...

React Draggable插件实现拖拽功能

React Draggable插件实现拖拽功能1.下载Draggable插件2.引入Draggable插件3.设置一个div&#xff0c;并设置样式&#xff0c;并用Draggable包裹起来4.设置拖拽的范围5.Draggable常用props1.下载Draggable插件 npm install react-draggable2.引入Draggable插件 // 引入拖拽插件…...

MySQL-运算符

算术运算符: 加法运算-: 减法运算*: 乘法运算/: 除法运算&#xff0c;返回商%: 求余运算&#xff0c;返回余数例&#xff1a;创建n5表&#xff0c;插入数字100&#xff0c;查看数据表分别查看、-、*、/、%mysql> create table n5(-> num int); Query OK, 0 rows affected…...

市场营销价格策略/绍兴百度推广优化排名

这次。。。。。。好像稍有起色&#xff1f; 不像前几次那么差了&#xff0c;但是还是不尽如人意 凭君莫话封侯事&#xff0c;一将功成万骨枯&#xff0c;也许是在暗示着什么吧 继续保持 简要说一下考试经历 上来肛T1&#xff0c;想岔了把前缀和相减想成了相加&#xff0c;复杂度…...

汕头网站建设和运营/浏览器2345网址导航下载安装

不经意地被一位同事问起在javascript里面如何检测右键事件&#xff0c;并且屏蔽原来的右键菜单&#xff0c;上网查找一翻之后发现一些比较简单的方法。如设置onmousedown&#xff0c;检查其event.button的值是不是2&#xff08;代表右键&#xff09;。这个方法在FF和IE中都可用…...

免费自己制作网站方法/辽源seo

先去下载https://dev.mysql.com/downloads/mysql/解压完是这个样子将这个文件放入到C盘并将文件名字改掉成MySQL配置初始化的my.ini文件的文件解压后的目录并没有的my.ini文件&#xff0c;没关系可以自行创建在安装根目录下添加的my.ini(新建文本文件&#xff0c;将文件类型改为…...

免费域名申请网站大全下载/重庆排名优化整站优化

前言一 编程规约 一 命名风格二 常量定义三 代码格式四 OOP规约五 集合处理六 并发处理七 控制语句八 注释规约九 其它 二 异常日志 一 异常处理二 日志规约 三 MySQL数据库 一 建表规约二 索引规约三 SQL语句四 ORM映射 四 工程结构 一 应用分层二 二方库依赖三 服务器 五 安全…...

怎么创建音乐网站/杭州网站建设网页制作

现在IT行业越来越火热&#xff0c;想要学习编程的人也越来越多。IT行业的薪资连续好几年赶超金融行业&#xff0c;位居行业之首&#xff0c;有太多人转行跨界&#xff0c;想要进入这个领域&#xff0c;那么作为初学者的你&#xff0c;是不是也很困惑&#xff0c;非科班出生&…...

做网站外包公司/优化落实疫情防控

1.题目描述&#xff1a; 2.算法分析&#xff1a; 首先&#xff0c;要过滤掉多余的空格&#xff0c;我们如果一个一个删除空格是一件很麻烦的事&#xff0c;不妨我们可以从每个单词的后面加一个空格&#xff0c;这样是不是会比把多余空格删除好一些呢。怎么做&#xff1f; 一个…...