类和对象 - 下
本文已收录至《C++语言》专栏!
作者:ARMCSKGT
目录
前言
正文
初始化列表
成员变量的定义与初始化
初始化列表的使用
变量定义顺序
explicit关键字
隐式类型转换
自定义类型隐式转换
explicit 限制转换
关于static
static声明类成员
友元
友元函数
友元函数特殊使用场景
友元类
内部类
概述
特性
匿名对象
编译器对于自定义类型的一些优化
隐式类型转换的优化
传参优化
返回值优化
说明
合理使用优化
关于对象的理解
最后
前言
前面我们介绍了类和对象的基本概念以及类的六个默认成员函数,这些知识已经为我们搭起了一个基本的类框架,不过类和对象中还有一些小细节需要介绍,本节我们将进入类和对象的收尾阶段!
正文
初始化列表
成员变量的定义与初始化
上篇我们学习了构造函数,构造函数是用来初始化成员变量的,而成员变量的定义是在初始化列表,对于一些需要在定义时就赋值的成员,例如 const int x ,这时需要使用初始化列表进行,因为在C++11之前,C++98并不支持在声明列表中给缺省值!
虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。
int num = 0; //在定义时赋初值 - 初始化 num = 1; //被定义后赋值 - 赋值
那么初始化列表与构造函数有什么关系呢?构造函数是对象在实例时就调用的一个函数,初始化列表在构造函数中,会随构造函数一起执行,初始化列表最先执行并将指定的值赋给每个成员变量!如果我们没有显示去写初始化列表编译器仍然会执行初始化列表,只不过内置类型初始化为随机值,自定义类型则调用其默认构造函数!
示例1:
class Date { public://猜猜下面两个构造函数的区别Date() //初始化列表初始化:_year(2008),_month(12),_day(21){_year = 0;_month = 0;_day = 0;}Date(size_t year, size_t month, size_t day) //函数内赋值{ _year = year;_month = month;_day = day;}private:size_t _year;size_t _month;size_t _day; };int main() {Date d1;Date d2(1970,1,1);return 0; }
使用初始化列表的构造函数 未使用初始化列表的构造函数 示例2:
class Test { public:Test() //a会被初始化为什么?:a(1){ } private:int a = 2; };int main() {Test t;return 0; }
编译器优先使用初始化列表中的初值进行初始化 初始化列表的使用
初始化列表:在函数参数()后,函数体前{},以一个(:)冒号开始,接着是一个以(,)逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式,最后一个列表成员后没有任何符号。
//1.所有对象的成员变量都是在初始化列表被定义的 //2.无论是否显示在初始化列表写,每个变量都会在初始化列表中被定义和初始化class Date { public:Date(int year = 1970, int month = 1, int day = 1):_year(year) //初始化列表初始化, _month(month), _day(day){//其他初始化行为 } private:int _year;int _month;int _day; };
注意
- 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
- 类中包含以下成员,必须放在初始化列表位置进行初始化:引用成员变量,const成员变量,自定义类型成员且该类没有默认构造函数时(简而言之就是需要在初始化指定初始值的成员变量)
//错误示例 class Test2 {Test2(int a) {} };class Test { public:Test() {} private:const int num; //这三种成员变量不使用初始化列表初始化是无法编译的!int& ref;Test2 t; };int main() {Test t;return 0; }
上述代码编译报错
因为构造函数中函数体是以赋值的方式初始化的,在执行赋值语句前,变量需要被定义和初始化,编译器默认的初始化手段是赋随机值,const只能在初始化阶段指定初始值,如果const常亮被赋予随机值是不合理的,这里也突出了构造函数的一些缺陷,为了补足这些缺陷,C++使用初始化列表定义和初始化且初始化列表存在与构造函数中!
节选自C++之父Scott Meyers名书Effective C++ (其中成员初值列就是初始化列表) 所以尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化!
变量定义顺序
成员变量既然在初始化列表定义,那定义的顺序是由什么觉得的?
成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关!
class Test { public:Test() //猜猜a会被初始化为1吗?: b(1), a(b){cout << a << endl;} private:int a = 0;int b = 0; };int main() {Test t;return 0; }
a在b前被定义但是b此时未被初始化所以是随机值 结论:成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。
所以这里建议:初始化列表顺序与成员变量声明顺序一致!
explicit关键字
我们在平时写代码中不妨会涉及类型转换,类的实例化也是,实例化对象时也会发生类型转换!
隐式类型转换
对于两个类型不同的变量,如果要赋值则需要进行类型转换。
int i = 0; double d = 1.23456; i = d; //这里会发生隐式类型转换
自定义类型隐式转换
//示例代码 class Test { public://默认构造函数Test(int num = 0):_num(num){cout << "构造函数" << endl;}//拷贝构造Test(const Test& t){_num = t._num;cout << "拷贝构造" << endl;}//赋值重载Test& operator=(const Test& t){_num = t._num;cout << "赋值重载" << endl;}private:int _num; };int main() {//初始化会成功吗?Test t = 10;return 0; }
很显然,初始化成功了,但是我想告诉大家,这次初始化调用了构造函数和拷贝构造和两个函数,进行了隐式类型转换然后初始化了 t 对象!
实际运行调用 这里大家可能会怀疑,上面解释的明明会调用两个构造函数,但是实际上却只调用了一个构造函数,这里要说明的是:编译器为了优化效率,将10直接对t进行构造(直接构造),这样可以提高效率!
Test t = 10; //这样效率太低了Test t(10); //编译器优化为直接构造
当然如果类初始化时有多参数参与初始化,也支持多参数构造优化!
class Test { public:Test(int a, int b): _a(a), _b(b){cout << "Test()" << endl;cout << "_a = " << _a << " " << "_b = " << _b << endl;} private:int _a = 0;int _b = 0; };int main() {Test t = { 1,2 };return 0; }
explicit 限制转换
铺垫了这么久,重点来了!
有时候我们不想使构造函数方式类型转换进行构造,可以在构造函数前加上 explicit 关键字禁止类型转换!
//示例代码 class Test { public://默认构造函数 - explicit修饰限制类型转换行为explicit Test(int num = 0):_num(num){cout << "构造函数" << endl;}//拷贝构造Test(const Test& t){_num = t._num;cout << "拷贝构造" << endl;}//赋值重载Test& operator=(const Test& t){_num = t._num;cout << "赋值重载" << endl;}private:int _num; };int main() {//初始化会成功吗?Test t = 10;return 0; }
此时类型转换也不存在了,编译器优化也就不存在了 所以,如果我们想要提高代码的可读和规范性,必要时使用explicit修饰构造函数就能防止实例化时发生类型转换!
关于static
在C语言的学习中,我们知道static是静态修饰,被修饰的变量生命周期增长至程序运行周期!但是我们平时在写代码时static必须得慎用,因为其中有很多细节需要我们考虑!
static声明类成员
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。
特性
- 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区。
- 静态成员变量必须在类外定义和初始化且只能初始化一次,定义时不添加static关键字,类中只是声明。
- 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问。
- 静态成员函数没有隐藏的this指针,不能访问任何非静态成员(这样就不需要实例化对象,只需要类名就能访问)。
- 静态成员函数只能访问静态成员,因为没有this指针无法调用其他非静态成员,静态成员函数是为了静态成员变量而生的。
- 静态成员也是类的成员,受public、protected、private 访问限定符的限制。
//示例 class Test { public://Test()// :a(0) //{} //不能在初始化列表初始化,因为静态成员a不属于任何一个单独的对象,a被所有对象共享static int a; //声明为静态成员 };int Test::a = 0; //类外定义和初始化静态成员 - 类型 类名::静态成员int main() {++Test::a; //通过类名 Test::a 访问静态成员cout << "Test::a : " << Test::a << endl;Test t;++t.a; //通过对象 t.a 访问静态成员cout << "t.a : " << Test::a << endl;return 0; }
重点总结: 静态成员不能调用非静态成员,因为没有this指针,但是非静态成员可以调用静态成员,因为静态成员具有全局属性!
由静态成员的特性,可以求出实例化了多少个对象!
因为实例化对象每次都会调用构造函数,我们可以定义一个静态成员计数器num,每次调用构造函数num就加1,最后就可以完成对构造函数调用次数的统计!
class Test { public:Test() //默认构造{cout << "Test() ";++num;}~Test() //析构函数{cout << "~Test() ";cout << "num = " << num << endl; //打印当前num}static int num; };int Test::num = 0;int main() {for (int i = 0; i < 10; ++i) //循环进行实例对象{Test t;}return 0; }
友元
概述:有些场景下,某些外部函数需要访问类私有和保护成员,友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。
友元分为:友元函数和友元类。
友元声明关键字: friend
友元函数
将函数使用friend修饰并声明在类中,则此函数称为该类的友元函数!
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明。
//区别示例 class Test {friend void fun1(const Test& t); //声明为友元函数 public:Test(int n = 0):mynum(n){}private:int mynum; };void fun1(const Test& t) {cout << t.mynum << endl; //友元函数可以直接访问对象的内部私有和保护成员 }void fun2(const Test& t) {cout << t.mynum << endl; //这里会报错 }//其他函数只能访问公开成员
特性
- 友元函数可访问类的私有和保护成员,但不是类的成员函数
- 友元函数不能用const修饰
- 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
- 一个函数可以是多个类的友元函数
- 友元函数的调用与普通函数的调用原理相同
友元函数特殊使用场景
自定义类型重载流提取和流插入运算符
问题:当我们尝试去重载operator<<,然后发现没办法将operator<<重载成成员函数。因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以要将operator<<重载成全局函数。但又会导致类外没办法访问成员,此时就需要友元来解决。operator>>同理。
//日期类重载流插入提取运算符 - 友元函数法 class Date {friend ostream& operator<<(ostream& _cout, const Date& d);friend istream& operator>>(istream& _cin, Date& d); public:Date(int year = 1970, 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;_cin >> d._month;_cin >> d._day;return _cin; }
友元类
使用 friend 修饰类并声明在其他类中可以成为该类的友元类!
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
class Time {friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量 public:Time(int hour = 0, int minute = 0, int second = 0): _hour(hour), _minute(minute), _second(second){} private:int _hour;int _minute;int _second; };class Date { public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}void SetTimeOfDate(int hour, int minute, int second){// 直接访问时间类私有的成员变量_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类中私有的成员变量则不行)
- 友元关系不能传递
- 如果C是B的友元, B是A的友元,则不能说明C时A的友元
- 友元关系不能继承
- 友元类可以在类定义的任何地方声明,不受类访问限定符限制
内部类
概述
如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。内部类就是外部类的友元类,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
class A { public:class B //B称为A的内部类{private:int Bnum;}; private:int Anum; };
这里B是A的内部类(友元类),A是B的外部类!B可以访问A类的所有成员,但是A不能访问B类的所有成员!
特性
- 内部类可以定义在外部类的public、protected、private都是可以的
- 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名
- 外部类的字节大小与内部类没有任何关系,两者相互独立
- 与友元类的区别:内部类能受到外类的访问限定符限制
- 内部类可以访问外类中的成员,而外类无法访问内部类的成员
内部类是平时使用极少,一般用于隐藏类!
匿名对象
class Test {Test(int n = 0):num(n){ cout<<"Test()"<<endl;}~Test(){ cout<<"~Test()"<<endl;} privateint num; };int main() {Test(); //构造匿名对象return 0; }
通过 类名() 的方式可以构造匿名对象,匿名对象最大的特性就是生命周期只在一行,对于一些对象只用一次的情况,可以使用匿名对象优化性能。
匿名对象的生命周期在某些条件下会延长,例如被const引用变量引用后,其生命周期延长至函数执行结束!
编译器对于自定义类型的一些优化
编译器在实例化,传参和隐式类型转换时并非按正常的流程运行,而是进行了一些优化(简化了执行流程),从而提升执行效率!
//示例代码 - 接下来的测试以此类进行 class Test { public:Test(int n = 0) //构造函数:num(n){cout<<"Test(int n = 0)"<<endl;}Test(const Test& t) //拷贝构造函数{num = t.num;cout<<"Test(const Test& t)"<<endl;}Test& operator=(const Test& t) //赋值重载函数{num = t.num;cout<<"operator="<<endl;return *this;}private:int num; };
隐式类型转换的优化
int main() {Test t = 10;return 0; }
优化前:int类型转换为Test类型都临时对象,拷贝构造临时对象构造对象 t .
//相当于 //10 -> Test tmp(10) -> Test t(tmp) // 先方式类型转换 再拷贝构造
优化后: 直接将10作为构造参数构造对象 t .
//相当于 Test t(10);
传参优化
void fun(Test t) {}int main() {fun(10);return 0; }
优化前:int类型转换为Test类型(与以上隐式类型转换相同),然后 t 通过拷贝构造形成对象.
//相当于 //10 -> Test tmp(10) -> Test t(tmp) // 先方式类型转换 再拷贝构造
优化后:直接构造形成对象.
这里与隐式类型转换的优化相似!
返回值优化
Test fun() {return Test(10); //匿名对象 }int main() { Test t = fun();return 0; }
优化前:构造匿名对象,返回匿名对象的拷贝临时变量,将临时对象拷贝构造形成对象 t.
优化后:通过返回的匿名对象,直接构造对象 t .
说明
- 引用传参时,编译器无需优化,因为不会涉及拷贝构造
- 实际编码时,如果能采用匿名构造,就用匿名构造,会加速编译器的优化
- 接收参数时,如果分成两行(先定义、再接收),编译器无法优化,效率会降低
编译器会将不必要的 拷贝构造和构造 步骤去掉,优化为直接构造!
编译器只能在一行语句内进行优化,如果将这些语句拆分为多条语句,编译器则不会优化,因为编译器不能擅自主张。
//例如 int main() {Test t;t = 10;return 0; }
合理使用优化
因为编译器对这些情况有优化,所以我们使用以下技巧可以提高程序效率!
- 接收返回值对象时,尽量拷贝构造方式接收,不要赋值接收
- 函数返回时,尽量返回匿名对象
- 函数参数尽量使用 const& 参数
关于对象的理解
现实生活中的实体计算机并不认识,计算机只认识二进制格式的数据。如果想要让计算机认识现实生活中的实体,用户必须通过某种面向对象的语言,对实体进行描述,然后通过编写程序,创建对象后计算机才可以认识。比如想要让计算机认识洗衣机,就需要:
- 用户先要对现实中洗衣机实体进行抽象---即在人为思想层面对洗衣机进行认识,洗衣机有什么属性,有那些功能,即对洗衣机进行抽象认知的一个过程。
- 经过1之后,在人的头脑中已经对洗衣机有了一个清醒的认识,只不过此时计算机还不清楚,想要让计算机识别人想象中的洗衣机,就需要人通过某种面相对象的语言(比如:C++、Java、Python等)将洗衣机用类来进行描述,并输入到计算机中
- 经过2之后,在计算机中就有了一个洗衣机类,但是洗衣机类只是站在计算机的角度对洗衣机对象进行描述的,通过洗衣机类,可以实例化出一个个具体的洗衣机对象,此时计算机才能洗衣机是什么东西。
- 用户就可以借助计算机中洗衣机对象,来模拟现实中的洗衣机实体了。
在类和对象阶段,大家一定要体会到,类是对某一类实体(对象)来进行描述的,描述该对象具有那些属性,那些方法,描述完成后就形成了一种新的自定义类型,才用该自定义类型就可以实例化具体的对象。
最后
<类和对象 - 下> 的知识介绍到这里就结束了!本篇介绍了类变量的定义在初始化列表以及初始化列表的合理使用,static成员的定义,友元概念和编译器的一些优化,相信这些细节的加持下,我们能加深对类和对象的理解,更加合理的使用类,类和对象的知识。类和对象的知识介绍到这里就结束了,希望小伙伴们都能理解!
本次 <C++类和对象 - 下> 就介绍到这里啦,希望能够尽可能帮助到大家。
如果文章中有瑕疵,还请各位大佬细心点评和留言,我将立即修补错误,谢谢!
🌟其他文章阅读推荐🌟
C++ <类和对象 - 中> -CSDN博客
C++ <类和对象 - 上> -CSDN博客
C++入门知识 -CSDN博客
🌹欢迎读者多多浏览多多支持!🌹
相关文章:
![](https://img-blog.csdnimg.cn/img_convert/35edba3b72a0ab22f56bc7f5b0722a85.jpeg)
类和对象 - 下
本文已收录至《C语言》专栏! 作者:ARMCSKGT 目录 前言 正文 初始化列表 成员变量的定义与初始化 初始化列表的使用 变量定义顺序 explicit关键字 隐式类型转换 自定义类型隐式转换 explicit 限制转换 关于static static声明类成员 友元 友…...
![](https://img-blog.csdnimg.cn/513cdcb73d914414aaa71065e8ba9a69.gif#pic_center)
【云原生】Linux基础IO(文件理解与操作)
✨个人主页: Yohifo 🎉所属专栏: Linux学习之旅 🎊每篇一句: 图片来源 🎃操作环境: CentOS 7.6 阿里云远程服务器 Great minds discuss ideas. Average minds discuss events. Small minds disc…...
![](https://www.ngui.cc/images/no-images.jpg)
CentOS 7 安装 mysql 8.0 客户端
只想安装 mysql-client 8.0 , 结果发现直接 yum install mysql mysql-client 安装的版本是 mysql Ver 15.1 Distrib 5.5.68-MariaDB ,这个版本太低,连接其他服务器上的 mysql 8.0 时总是失败,因为 mysql 8.0 加密方式改变了&#…...
![](https://img-blog.csdnimg.cn/img_convert/3b5a0c4bdca64fe4920164cdfe346ac6.png)
Ubuntu下载、配置、安装和编译opencv
1 安装相关依赖安装opencv前,需要先准备好编译器、相关依赖sudo apt-get install gcc g cmake vim sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-dev libjpeg-dev libswscale-dev libtiff5-dev sudo apt-get install libgtk2.0-…...
![](https://img-blog.csdnimg.cn/c08bf7a248e346a58b2dc8fe540f9c57.png)
第七讲 贪心
文章目录股票买卖 II货仓选址(贪心:排序中位数)糖果传递(❗贪心:中位数)雷达设备(贪心排序)付账问题(平均值排序❓)乘积最大(排序/双指针)后缀表达…...
![](https://www.ngui.cc/images/no-images.jpg)
数字藏品的未来及发展趋势
随着互联网的普及以及数字文化的日益发展,数字藏品作为一种全新的收藏方式正在逐步兴起。数字藏品可以是数字版权、数字艺术品、数字音乐以及数字视频等形式,这些藏品通过数字化技术保存下来,并在互联网上进行传播和交易。数字藏品的发展趋势…...
![](https://img-blog.csdnimg.cn/17b35b5ed6e64720b913e1f588be6f78.jpeg)
值得记忆的STL常用算法,分分钟摆脱容器调用的困境,以vector为例,其余容器写法类似
STL常用算法 概述: 算法主要是由头文件<algorithm> <functional> <numeric>组成 <algorithm>是所有STL头文件中最大的一个,范围涉及到比较、交换、查找、遍历操作、复制、修改等等 <nuneric>体积很小,只包括…...
java如何手动导jar包
今天用IDEA,需要导入一个Jar包,因为以前都是用eclipse的,所以对这个idea还不怎么上手,连打个Jar包都是谷歌了一下。 但是发现网上谷歌到的做法一般都是去File –> Project Structure中去设置,有没有如同eclipse一样…...
![](https://www.ngui.cc/images/no-images.jpg)
怎么防止SQL注入?
首先SQL注入是一种常见的安全漏洞,黑客可以通过注入恶意代码来攻击数据库和应用程序。以下是一些防止SQL注入的基本措施: 数据库操作层面 使用参数化查询:参数化查询可以防止SQL注入,因为参数化查询会对用户输入的数据进行过滤和…...
![](https://img-blog.csdnimg.cn/d56ca138eacd4b729e9d341d1ad9937c.jpeg)
【千题案例】TypeScript获取两点之间的距离 | 中点 | 补点 | 向量 | 角度
我们在编写一些瞄准、绘制、擦除等功能函数时,经常会遇到计算两点之间的一些参数,那本篇文章就来讲一下两点之间的一系列参数计算。 目录 1️⃣ 两点之间的距离 ①实现原理 ②代码实现及结果 2️⃣两点之间的中点 ①实现原理 ②代码实现及结果 3…...
![](https://img-blog.csdnimg.cn/ea6c74bbf4a04dc78883e0264f7582fd.png)
堆叠注入--攻防世界CTF赛题学习
在一次联系CTF赛题中才了解到堆叠注入,在这里简单介绍一下。 堆叠注入的原理什么的一搜一大堆,我就不引用百度了,直接进入正题。 这个是攻防世界的一道CTF赛题。 采用寻常思路来寻找sql注入漏洞。 payload:1 and 11-- 利用payload: and 12…...
![](https://img-blog.csdnimg.cn/img_convert/d09b30dda49838b5e09488a48d320c60.png)
STM32 ADC+定时器+DMA+FFT
本次实现的功能为单片机DAC输出一个正弦波,然后ADC定时采样用DMA输出,最后对DAC输出的波形进行FFT。单片机STM32F103ZET6内部时钟一、配置ADCADC端口为PA1,采用DMA输出,定时器3触发定时器时钟64M,分频后为102.4KHzADC采…...
![](https://www.ngui.cc/images/no-images.jpg)
用Node.js实现一个HTTP服务器程序(文件服务器)
http Node.js开发的目的就是为了用JavaScript编写Web服务器程序。因为JavaScript实际上已经统治了浏览器端的脚本,其优势就是有世界上数量最多的前端开发人员。如果已经掌握了JavaScript前端开发,再学习一下如何将JavaScript应用在后端开发,就是名副其实的全栈了。 HTTP协…...
![](https://img-blog.csdnimg.cn/227820fabcfc48f98a3f9192febec938.gif)
Python实现人脸识别检测, 对美女主播照片进行评分排名
前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 素材、视频、代码、插件安装教程我都准备好了,直接在文末名片自取就可点击此处跳转 开发环境: Python 3.8 Pycharm 2021.2 模块使用: requests >>> pip install requests tqdm >…...
![](https://img-blog.csdnimg.cn/5261bf2a11124b798cf2e02aeb0bb25e.png)
【数据结构与算法】什么是双向链表?并用代码手动实现一个双向链表
文章目录一、什么是双向链表二、双向链表的简单实现一、什么是双向链表 我们来看一下这个例子: 在一个教室里,所有的课桌排成一列,如图 相信在你们的读书生涯中,老师肯定有要求你们记住自己的前后桌是谁。所以该例子中&#x…...
![](https://img-blog.csdnimg.cn/3a8e83662fea495baa36475c12c3922c.png)
23种设计模式
参考链接: 【狂神说Java】通俗易懂的23种设计模式教学(停更)_哔哩哔哩_bilibili 23种设计模式【狂神说】_狂神说设计模式_miss_you1213的博客-CSDN博客 1. 单例模式 参考链接: 【狂神说Java】单例模式-23种设计模式系列_哔哩哔哩…...
![](https://www.ngui.cc/images/no-images.jpg)
20美刀一个月的ChatGPT架构师,性价比逆天了
文章目录20美刀一个月的ChatGPT架构师,性价比逆天了1.角色设定2.基本描述3.解决方案4.物理网络蓝图5.系统集成接口5.1 系统集成接口设计5.1.1 前端服务器与后端服务器接口:5.1.2 后端服务器与去背景处理服务接口:5.2 系统集成接口展示6.部署环…...
![](https://www.ngui.cc/images/no-images.jpg)
海门区教育科学规划课题2020年度成果鉴定书
海门区教育科学规划课题2020年度成果鉴定书 课题编号:HMGZ2020007 课题名称 中学历史核心素养校本化实施的培育研究 主持人 徐彬 工作单位 南通市海门证大中学 核心组成员 (包括主持人) 姓名 研究任务完成情况 (获得的主要成果、…...
![](https://www.ngui.cc/images/no-images.jpg)
大数据专业应该怎么学习
大数据学习不能停留在理论的层面上,大数据方向切入应是全方位的,基础语言的学习只是很小的一个方面,编程落实到最后到编程思想。学习前一定要对大数据有一个整体的认识。 大数据是数据量多吗?其实并不是,通过Hadoop其…...
![](https://img-blog.csdnimg.cn/img_convert/2bb8cbc9344106d137781f8b514ef478.jpeg)
学习黑客十余年,如何成为一名高级的安全工程师?
1. 前言 说实话,一直到现在,我都认为绝大多数看我这篇文章的读者最后终究会放弃,原因很简单,自学终究是一种适合于极少数人的学习方法,而且非常非常慢,在这个过程中的变数过大,稍有不慎&#…...
![](https://img-blog.csdnimg.cn/a7d74ccc26644779aefa1e9785b71b86.png)
【算法】手把手学会二分查找
目录 简介 基本步骤 第一种二分 第二种二分 例题 搜索插入位置 数的范围 总结 简介 🥥二分查找,又叫折半查找,通过找到数据二段性每次都能将原来的数据筛选掉一半,通过这个算法我们能够将一个一个查找的 O(n) 的时间复杂…...
![](https://www.ngui.cc/images/no-images.jpg)
SVO、vinsmono、 OKVIS系统比较
几个经典视觉slam系统的比较 SVO 高翔链接:https://www.zhihu.com/question/39904950/answer/138644975处理的各个线程: tracking部分-frame to frame 、frame to map 金字塔的处理。这一步估计是从金字塔的顶层开始,把上一层的结果作为下一层估计的初…...
![](https://www.ngui.cc/images/no-images.jpg)
前端开发规范
一、开发工具 开发工具统一使用 VSCode代码格式化插件使用 Prettier代码格式校验使用 ESLintVSCode 需安装的插件有:ESLint、Prettier、Vetur 二、命名规范 项目命名使用小写字母,以连字符分隔 正确:fe-project 错误:FE PROJECT…...
![](https://img-blog.csdnimg.cn/img_convert/7795cb1f35442887b891cf7b3665a2de.png)
不用科学上网,免费的GPT-4 IDE工具Cursor保姆级使用教程
大家好,我是可乐。 过去的一周,真是疯狂的一周。 GPT-4 震撼发布,拥有了多模态能力,不仅能和GPT3一样进行文字对话,还能读懂图片; 然后斯坦福大学发布 Alpaca 7 B,性能匹敌 GPT-3.5ÿ…...
![](https://www.ngui.cc/images/no-images.jpg)
【艾特淘】抖音小店物流体验分提升的6个维度,新手做店必看
抖音小店体验分,考核的内容包括商品、物流以及服务。大部分人会把重心放在商品评价和服务上,忽略了物流体验。但其实,抖音小店物流体验占比有20%,比服务分的占比还高一点。如果你的订单物流出了问题,很有可能会导致用户…...
![](https://img-blog.csdnimg.cn/9c152e18a85b46f78bb7ca2919c1a56f.png)
数据结构——二叉树与堆
作者:几冬雪来 时间: 内容:二叉树与堆内容讲解 目录 前言: 1.完全二叉树的存储: 2.堆的实现: 1.创建文件: 2.定义结构体: 3.初始化结构体: 4.扩容空间与扩容…...
![](https://img-blog.csdnimg.cn/4076c3bedf0e4d40aff5ac08352a9850.png)
Three.js——learn02
Three.js——learn02Three.js——learn02通过轨道控制器查看物体OrbitControls核心代码index2.htmlindex.cssindex2.jsresult添加辅助器1.坐标轴辅助器AxesHelper核心代码完整代码2.箭头辅助器ArrowHelper核心代码完整代码3.相机视锥体辅助器CameraHelper核心代码完整代码Three…...
![](https://img-blog.csdnimg.cn/img_convert/e992045027882e8f94d70ab26ed681cc.png)
零基础小白如何入门网络安全?
我经常会看到这一类的问题: 学习XXX知识没效果; 学习XXX技能没方向; 学习XXX没办法入门; 给大家一个忠告,如果你完全没有基础的话,前期最好不要盲目去找资料学习,因为大部分人把资料收集好之…...
![](https://img-blog.csdnimg.cn/b0dd2b2f8dca48ccb12d594f0d6e3060.png)
【前缀和】
前缀和前缀和子矩阵的和结语前缀和 输入一个长度为 n的整数序列。 接下来再输入 m 个询问,每个询问输入一对 l,r 对于每个询问,输出原序列中从第 l 个数到第 r个数的和。 输入格式第一行包含两个整数 n和 m 第二行包含 n个整数,表示整数…...
ChatGPT可以做WebRTC音视频质量性能优化,惊艳到我了
摘要 随着GPT-4的发布,AI的风越吹越旺。GPT-4可以回答问题,可以写作,甚至可以基于一张草图生成html代码搭建一个网站。即构社区的一位开发者倪同学就基于目前在研究的WebRTC QOS技术点对GPT-3.5跟GPT-4进行一场实验,ChatGPT会取代…...
![](https://www.oschina.net/img/hot3.png)
营销型网站建设项目需求表/行业关键词搜索量排名
2019独角兽企业重金招聘Python工程师标准>>> 之前我看到很多和这个差不多的方法 Date date1 new Date(); SimpleDateFormat sdf1 new SimpleDateFormat("yyyy-MM-dd"); String str1 sdf1.format(date1)用上面这个的话还是报错,类型…...
wordpress怎么添加网盘下载/seo站长博客
1. 获取镜像可以利用已有的FastDFS Docker镜像来运行FastDFS。获取镜像可以通过下载docker image pull delron/fastdfs也可是直接使用提供给大家的镜像备份文件文件下载地址:链接:https://pan.baidu.com/s/1tB0Pk9NAeeyuKXOSkgVuwQ提取码:ry1…...
![](https://img-blog.csdnimg.cn/92166a17a189438f8110aa848adf98fd.gif#pic_center)
河北网站开发多少钱/如何免费推广一个网站
文章目录流程循环数组简单案例先看看效果图 流程 使用数组的slice() 方法通过条件判断截取原数组相应内容组成新数组 循环数组 let currentPage 0 // arr:原数组 newLen:新数组需要的长度 currentPage:现在的页码// 方法一: function loopData(arr, newLen) {…...
![](http://pcx55bat1.bkt.clouddn.com/avro1.png)
聊天网站备案/网站关键词优化怎么弄
Apache Avro 是一个独立于编程语言的数据序列化系统。旨在解决Hadoop中Writable类型的不足:缺乏语言的可移植性。Avro 模式通常用json来写,数据通常采用二进制格式编码。 Avro的使用 Avro 的使用可以分为两种:编译Schema和非编译Schema 编译S…...
![](/images/no-images.jpg)
网站营销策略怎么写/网络营销环境
...
![](https://images2018.cnblogs.com/blog/339342/201805/339342-20180504202430550-365649759.png)
老闵行房价/搜索引擎营销优化诊断训练
最近因需要,翻出几年前的Leapmotion感测器,准备用Unity3D做个互动APP,于是连上官网下载SDK。等下载下来一安装调试,瞬间傻眼,居然要求VR设备。我们Lab倒是不缺VR,有几套VIVE,不过不能保证甲方也…...