【C++】 类和对象 (下)
文章目录
- 📕再谈构造函数
- 1. 构造函数体赋值
- 2. 初始化列表
- 3. explicit 关键字
- 📕static 成员
- 1. 概念
- 2. static 成员变量
- 3. static 成员函数
- 📕 友元
- 1. 友元函数
- 2. 友元类
- 📕内部类
- 📕编译器优化
📕再谈构造函数
1. 构造函数体赋值
在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。
class Date {
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};
虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对 对象中 成员变量 的初始化,构造函数体中的语句只能将其称为赋初值
,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。
对于上面普通的成员变量,不初始化当然没有关系,但是比如下面的呢?
main 函数中 定义了一个 aa 对象,这是对这个对象的定义,并没有定义其内部的成员变量。
引用、const修饰的成员变量、无默认构造的自定义类型成员。(默认构造:无参、全缺省、编译器自动生成的构造函数) 对于这三类成员变量,前两个都是要在定义的地方初始化,第三个无法传参。所以,必须要有一个 将成员变量初始化 的途径。
对于前两者,当然可以考虑使用缺省值,但是,缺省值是在 C++ 11 才出现的,那么之前是怎么解决的呢?
C++ 使用初始化列表
,来完成该功能。
class B
{
public:B(int n):_b(0){cout << "B()" << endl;}private:int _b;
};class A
{
public:private:int _a1=1; // 声明int _a2=2;// 引用 、const修饰 、没有默认构造 的 自定义类型成员const int _x;int& _ref; B bb;
};int main()
{const int t = 10; // const 修饰,只能初始化的时候给值A aa; // 对象的整体定义,每个成员什么时候定义呢?return 0;
}
2. 初始化列表
初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。
如下,A 中给出了初始化列表,可以简单的理解为在构造函数中间加一点"东西"。
按照初始化列表里面从上到下的顺序来看就是:初始化 _x 为 1 、初始化 _ref 为 _a 的引用 、初始化bb 并且传参为 4(自定义类型,调用它的初始化列表)。
然后函数体里面进行 _a1++ 、 _a2-- 操作。
class B
{
public:B(int n):_b(0){cout << "B()" << endl;}private:int _b;
};class A
{
public:A():_x(1), _ref(_a1) // 初始化成对 _a1 的引用, bb(4) // B 类的初始化列表有参数,没有默认构造(无参数),需要传参,必须这样写{_a1++;_a2--;}
private:int _a1=1; // 声明int _a2=2;// 引用 、const修饰 、没有默认构造 的 自定义类型成员const int _x;int& _ref; // 引用也要在定义的地方初始化B bb;
};int main()
{const int t = 10; // const 修饰A aa; // 对象的整体定义return 0;
}
成员在初始化列表中的顺序,并不就是它们的初始化顺序。
如下代码,运行结果是:输出 1 随机值 。
因为初始化列表里面,初始化顺序是 声明的顺序,而 不是 初始化列表里面的顺序。(如果是按照初始化列表里的顺序,那么 _a1 先初始化为参数的值,_a2 再初始化为 _a1 的值)
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();
}
所以,初始化列表有以下的一些注意点:
-
- 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)。
-
- 类中包含以下成员,必须放在初始化列表位置进行初始化:
- 引用 成员变量
- const 成员变量
- 自定义类型成员(且该类没有默认构造函数时)
-
- 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
-
- 成员变量在类中声明的次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。
我们再来体会一下单参数和多参数的区别。
引用 那一篇文章有写到,内置类型 转换成 自定义类型的引用,必须要用 const 修饰,因为是先将内置类型 放到 临时变量里面,而临时变量具有常性,所以为了避免权限放大,要用 const 修饰。比如下面 main 函数里的第一行代码。
但是对于单个参数的构造函数而言,如果也像下面注释一样,先 构造 临时变量、再将 临时变量 拷贝构造给 a2,未免过于麻烦,所以有的编译器就会优化,将这两个过程合二为一,直接当成构造,1 就相当于传过去的参数。
如下,根据输出结果,也可以看出没有调用拷贝构造。
class A {
public:A(int a):_a1(a){cout << "A(int a)" << endl;}A(const A& a){cout << "A(const A& a)" << endl;}private:int _a1;
};int main()
{const A& a3 = 1; // 将 1 放到 A 类型的 临时变量里面。临时变量具有常性,所以要const修饰// 单个参数A a1(1);A a2 = 1; // 隐式类型转换, 将 1 当作参数,调用初始化列表,有了 A 类型的临时变量,将临时变量拷贝给 a2return 0;
}
C++ 一开始是不支持多参数的,后来也支持了,其用法和单参数类似,只不过是使用的时候,要用大的花括号。
class A {
public:A(int a,int b):_a1(a){cout << "A(int a)" << endl;}A(const A& a){cout << "A(const A& a)" << endl;}private:int _a1;
};int main()
{// 多个参数A b1(1, 2);A b2 = { 2,2 }; // 多参数这样写const A& b3 = { 4,7 };return 0;
}
3. explicit 关键字
构造函数不仅可以构造 初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值
的构造函数,还具有类型转换的作用,从上面两段代码也可以看出来(将 内置类型转换成了自定义类型)。
但是,如果我们不需要构造函数的类型转换功能,也是可以的,只要用 explicit 修饰构造函数即可。
如下,explicit 修饰之后,依然强制类型转换,会报错。
class A {
public:explicit A(int a):_a1(a){cout << "A(int a)" << endl;}A(const A& a){cout << "A(const A& a)" << endl;}private:int _a1;
};int main()
{// 如果不想让内置类型,转换为自定义类型,可以在初始化列表的函数前面用 explicit 修饰A a = 1; // 报错return 0;
}
📕static 成员
1. 概念
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。
静态成员变量一定要在类外进行初始化。
2. static 成员变量
如果要 实现一个类A,计算程序中实例化了多少个A类型的对象。
最先想到的就是,在全局设置一个变量,每一次 构造 或者 拷贝 的时候,该变量的值都 +1 ,这样就可以计算实例化出了多少个对象。
但是,有了 static 成员的知识储备,就可以在类里面实现,这样子能更好地体现“封装
”的性质。
如下代码,static 修饰的成员变量 count,不属于某个具体的对象,而是属于整个类。在类里面只是声明,并不是定义,并且在类外定义的时候,是不要加 static 的。
但是如果成员变量在类里面被 private 修饰,那么就不可以访问到。所以必须要用 public 修饰,但是用 public 修饰之后,又可以被任意访问修改。
这样子就又出现了一个问题,如何才可以 不用public 修饰成员变量的情况下,还可以访问到count呢?这里要用static成员函数解决。
class A {
public:A(int a):_a1(a){count++;cout << "A(int a)" << endl;}A(const A& a){count++;cout << "A(const A& a)" << endl;}static int Size() // 静态成员函数,没有 this 指针,所以无法访问非静态的成员变量{return count;}public:int _a1;static int count; // 声明。此外,这个成员变量不属于某个对象,属于整个类
};int A::count=0; // 初始化int main()
{// count 需要变成 public 才可以被外部访问到A aa(2);cout << aa.count << endl;cout << A::count << endl;return 0;
}
3. static 成员函数
static 修饰的成员函数,没有 this 指针。所以,该函数内部不可以对 类 里面的非静态成员变量
进行访问。
如下,static 修饰的 Size() 函数,只能访问静态成员变量 count ,不可以访问非静态成员变量 _a1 ,因为该函数的参数是没有 this 指针的。
从某种程度上来说,静态成员函数就是为了静态成员变量而创造的。
下面的代码,通过 Size() 函数 返回 count 的值,但是却不会对 count 进行任何修改(因为返回值是拷贝进临时变量的)。所以是最完美的结果,“封装”性体现的很好。
class A {
public:A(int a):_a1(a){count++;cout << "A(int a)" << endl;}A(const A& a){count++;cout << "A(const A& a)" << endl;}static int Size() // 静态成员函数,没有 this 指针,所以无法访问非静态的成员变量{return count;}private:int _a1;static int count; // 声明。此外,这个成员变量不属于某个对象,属于整个类
};int A::count=0; // 初始化int main()
{// 定义静态成员函数,这个函数返回 count 的值cout << A::Size() << endl;cout << A(1).Size() << endl; // 匿名对象,生命周期只在这一行return 0;
}
static 成员的一些特性:
- 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区。
- 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明。
- 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问。
- 静态成员函数没有隐藏的this指针,不能访问任何非静态成员。
- 静态成员也是类的成员,受public、protected、private 访问限定符的限制。
📕 友元
友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。
友元分为:友元函数和友元类。
1. 友元函数
如下代码,当我们想要在一个类里面对流输出
进行重载的时候,使用起来 是 d1<< cout; 和常规使用方式反了。所以,要么在iostream 标准库里面添加重载,要么在外部写流输出重载,前者显然不现实。但是,在类的外部写流输出重载的时候,无法访问类的成员变量,也就无法输出对应的值。
此时就需要友元函数的介入。
class Date {
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}// d1 << cout; -> d1.operator<<(&d1, cout); 不符合常规调用
// 因为成员函数第一个参数一定是隐藏的this,所以d1必须放在<<的左侧ostream& operator<<(ostream& _cout){_cout << _year << "-" << _month << "-" << _day << endl;return _cout;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2023,2,8);d1<<cout;
}
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加 friend 关键字。
如下代码,在 Date 类里面 申明 流输入重载、流输出重载,同时在两个函数的前面都加上 friend 。就代表这两个函数,是 Date 类的友元函数,可以访问 Date 类里面的成员变量。
两个函数的函数定义里面也可以看出来,传入的第二个参数是 d 的引用,但是 Date 类里面,成员变量都是 private 修饰的,那么即使是实例化的对象,也无法访问。但是由于两个函数都是Date类的友元函数,所以可以直接访问。
class Date {friend ostream& operator<<(ostream& _cout, const Date& d);friend istream& operator>>(istream& _cin, Date& d);
public:Date(int year = 1900, 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;
}int main()
{Date d;cin >> d;cout << d << endl;return 0;
}
友元函数的一些性质:
- 友元函数可访问类的私有和保护成员,但不是类的成员函数。
- 友元函数不能用const修饰。
- 友元函数可以在类定义的任何地方声明,不受类访问限定符限制。
- 一个函数可以是多个类的友元函数。
- 友元函数的调用与普通函数的调用原理相同。
2. 友元类
联想友元函数的声明以及用法,友元类也差不多。友元类
的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
如下,在 Time 类里面声明,Date 类是 Time 类的友元类,那么 Date 类里面的任何一个成员函数,都可以直接访问 Time 类里面的成员变量。
但是,这样的关系是单向的—— Time 类 里面的成员函数,不可以直接访问 Date 类的成员变量。
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){
// 直接访问 Time 类私有的成员变量_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的友元。
📕内部类
如果一个类定义在另一个类的内部,这个在内部的类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。
内部类其实就是外部类的友元类,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
比如下方的例子,B类在A类的内部,是A类的内部类。所以,B天生就是A的友元类,函数中可以通过A类的对象访问A类的成员变量(比如 foo 函数种,通过 a 访问 h) 。
另外,下方输出结果,sizeof(aa),结果是 8,并没有计算类型B里面的成员变量。这是因为,虽然B是A的内部类,但两个类是独立的,仅仅相当于B被隐藏起来了而已。
class A {
private:static int k;int h;
public:class B { // B天生就是A的友元public:void foo(const A& a){cout << k << endl;//OKcout << a.h << endl;//OK}};private:int _b1;double _b2;
};int A::k = 1;int main()
{A::B b;b.foo(A());A aa;cout<<sizeof(aa)<<endl;return 0;
}
使用内部类的情况也不多,下面是它的特性:
- 内部类可以定义在外部类的public、protected、private都是可以的。
- 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
- sizeof(外部类)=外部类,和内部类没有任何关系。
📕编译器优化
在函数传参和传返回值的过程中,一般编译器会做一些优化,减少对象的拷贝,这个在一些场景下还是非常有用的。
如下代码,在构造函数、拷贝构造、赋值重载、析构 这些函数体里面,都使用了流输出,只要调用函数,就会打印相应的内容,调试就可以知道某一行代码具体干了什么。
如下,将内置类型的 1 强制转换成A 类型的 aa1,按照之前理解的,要先构造为临时变量,然后临时变量拷贝构造给 aa1 。但是编译器会优化成直接构造,1 就是传的参数。
func(aa1) 要将实参拷贝为形参,所以调用一次拷贝构造。
func1(2); 先将 2 强制类型转换成 A 类型的临时变量,再将临时变量拷贝构造为形参。所以要先构造,再拷贝,但是编译器优化为直接构造。
func1(A(3)); 先以3为参数进行构造成为实参,再拷贝构造传给形参。优化为直接构造。
fuc2() 测试的是传引用,由于传引用不存在把实参拷贝构造给形参,所以没有优化的空间。
class A {
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}A(const A& aa):_a(aa._a){cout << "A(const A& aa)" << endl;}A& operator=(const A& aa){cout << "A& operator=(const A& aa)" << endl;if (this != &aa) {_a = aa._a;}return *this;}~A(){cout << "~A()" << endl;}
private:int _a;
};void func1(A aa)
{}void func2(const A& aa)
{}int main()
{A aa1 = 1; // 构造+拷贝构造 -》 优化为直接构造func1(aa1); // 无优化func1(2); // 构造+拷贝构造 -》 优化为直接构造func1(A(3)); // 构造+拷贝构造 -》 优化为直接构造cout << "----------------------------------" << endl;func2(aa1); // 无优化func2(2); // 无优化func2(A(3)); // 无优化return 0;
}
如下,A 依然是上面的类,一摸一样。改变的是两个外部函数,返回值传A类型的,并且函数内部定义A类型的对象。
直接调用 fuc3() ,无疑,先构造 aa ,再拷贝构造出一个临时变量作为返回值。所以调用了构造、拷贝构造。但是没有优化的空间,因为 func3() 函数内部 aa的 定义 和 返回是分开的。
A aa1=func3(); 调用 fun3 的过程和上面一样,先构造、再拷贝构造。生成的临时变量再拷贝构造给 aa1 ,所以经历了两次拷贝构造,此时就会被优化成一个拷贝构造。
但是,对于 aa2 而言,aa2 已经定义好了,aa2 = func3(); 是赋值重载,而不是拷贝构造,所以无法优化。
对于 func4(); 它直接构造出一个匿名对象返回,相当于构造和拷贝构造是连续的,所以可以优化为构造。
A aa3 = func4(); 除了调用 func4() ,还多了将 func4() 生成的临时变量,拷贝构造给 aa3 的过程,所以是 构造、拷贝构造、拷贝构造。编译器会优化成 构造。
A func3()
{A aa;return aa; // 不可以优化,因为分开的
}A func4()
{return A(); // 可以优化
}int main()
{func3();A aa1 = func3(); // 拷贝构造+拷贝构造 -- 优化为一个拷贝构造cout << "****" << endl;A aa2;aa2 = func3(); // 不能优化 , 因为是赋值重载cout << "---------------------------" << endl;func4(); // 构造+拷贝构造 -- 优化为构造A aa3 = func4(); // 构造+拷贝构造+拷贝构造 -- 优化为构造return 0;
}
上面所提到的一些优化,对于A类而言,确实没有什么区别,但是如果对于二叉树那些的呢?多次拷贝开销很大,所以,要学会使用这些小技巧,让程序更加优质!
这里浅浅地总结一下:
- 如果可以,尽量 return 匿名对象。
- 函数传参,尽量传引用。
- 如果要用一个对象来初始化另一个对象,尽量使用拷贝构造而不是赋值重载。
类和对象部分到这一篇文章就算是完结啦!有什么错误的地方欢迎指正!!
相关文章:
【C++】 类和对象 (下)
文章目录📕再谈构造函数1. 构造函数体赋值2. 初始化列表3. explicit 关键字📕static 成员1. 概念2. static 成员变量3. static 成员函数📕 友元1. 友元函数2. 友元类📕内部类📕编译器优化📕再谈构造函数 1…...
asp获取毫秒时间戳的方法 asp获取13位时间戳的方案
一、背景。时间戳就是计算当前与"1970-01-01 08:00:00"的时间差,在asp中通常是使用Datediff函数来计算两个日期差,代码:timestamp Datediff("s", "1970-01-01 08:00:00",now)返回结果:1675951060可…...
Python基础篇(十五)-- Python程序接入MySQL数据库
程序运行时,数据都在内存中,程序终止时,需要将数据保存到磁盘上。为了便于程序保存和读取,并能直接通过条件快速查询到指定数据,数据库(Database)应运而生,本篇主要学习使用Python操作数据库,在…...
程序员不得不知道的 API 接口常识
说实话,我非常希望自己能早点看到本篇文章,大学那个时候懵懵懂懂,跟着网上的免费教程做了一个购物商城就屁颠屁颠往简历上写。 至今我仍清晰地记得,那个电商教程是怎么定义接口的: 管它是增加、修改、删除、带参查询…...
【项目精选】基于Java的银行排号系统的设计与实现
银行排号系统是为解决一些服务业营业大厅排队问题而设计的,它能够有效地提高工作人员的工作效率,也能够使顾客合理的安排等待时间,让顾客感到服务的公平公正。论文首先讨论了排号系统的背景、意义、应用现状以及研究与开发现状。本文在对C/S架…...
前端 基于 vue-simple-uploader 实现大文件断点续传和分片上传
文章目录一、前言二、后端部分新建Maven 项目后端pom.xml配置文件 application.ymlHttpStatus.javaAjaxResult.javaCommonConstant.javaWebConfig.javaCheckChunkVO.javaBackChunk.javaBackFileList.javaBackChunkMapper.javaBackFileListMapper.javaBackFileListMapper.xmlBac…...
解决报错: ERR! code 128npm ERR! An unknown git error occurred
在github下载的项目运行时,进行npm install安装依赖时,出现如下错误:npm ERR! code 128npm ERR! An unknown git error occurrednpm ERR! command git --no-replace-objects ls-remote ssh://gitgithub.com/nhn/raphael.gitnpm ERR! gitgithu…...
聊城高新技术企业认定7项需要注意的问题 山东同邦科技分享
聊城高新技术企业认定7项需要注意的问题 山东同邦科技分享 山东省高新技术企业认定办公室发布《关于开展2021年度本市高新技术企业认定管理工作的通知》,高企认定中有哪些问题需要注意呢?下面我们一起来看一下。 一、知识产权 知识产权数量和质量双达…...
菊乐食品更新IPO招股书:收入依赖单一地区,规模不及认养一头牛
近日,四川菊乐食品股份有限公司(下称“菊乐食品”)预披露更新招股书,准备在深圳证券交易所主板上市,保荐机构为中信建投证券。据贝多财经了解,这已经是菊乐食品第四次冲刺A股上市,此前三次均未能…...
Elasticsearch安装IK分词器、配置自定义分词词库
一、分词简介 在Elasticsearch中,假设搜索条件是“华为手机平板电脑”,要求是只要满足了其中任意一个词语组合的数据都要查询出来。借助 Elasticseach 的文本分析功能可以轻松将搜索条件进行分词处理,再结合倒排索引实现快速检索。Elasticse…...
Linux嵌入式开发——shell脚本
文章目录Linux嵌入式开发——shell脚本一、shell脚本基本原则二、shell脚本语法2.1、编写shell脚本2.2、交互式shell脚本2.3、shell脚本的数值计算2.4、test命令&&运算符||运算符2.5、中括号[]判断符2.6、默认变量三、shell脚本条件判断if thenif then elsecase四、she…...
CV【5】:Layer normalization
系列文章目录 Normalization 系列方法(一):CV【4】:Batch normalization Normalization 系列方法(二):CV【5】:Layer normalization 文章目录系列文章目录前言2. Layer normalizati…...
跳跃游戏 II 解析
题目描述给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i j] 处:0 < j < nums[i] i j < n返回到达 nums[n - 1] 的…...
易基因|猪肠道组织的表观基因组功能注释增强对复杂性状和人类疾病的生物学解释:Nature子刊
大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。2021年10月6日,《Nat Commun》杂志发表了题为“Pig genome functional annotation enhances the biological interpretation of complex traits and human disease”的研究论文…...
01- NumPy 数据库 (机器学习)
numpy 数据库重点: numpy的主要数据格式: ndarray 列表转化为ndarray格式: np.array() np.save(x_arr, x) # 使用save可以存一个 ndarray np.savetxt(arr.csv, arr, delimiter ,) # 存储为 txt 文件 np.array([1, 2, 5, 8, 19], dtype float32) # 转换…...
RapperBot僵尸网络最新进化:删除恶意软件后仍能访问主机
自 2022 年 6 月中旬以来,研究人员一直在跟踪一个快速发展的 IoT 僵尸网络 RapperBot。该僵尸网络大量借鉴了 Mirai 的源代码,新的样本增加了持久化的功能,保证即使在设备重新启动或者删除恶意软件后,攻击者仍然可以通过 SSH 继续…...
拦截器interceptor总结
拦截器一. 概念拦截器和AOP的区别:拦截器和过滤器的区别:二. 入门案例2.1 定义拦截器bean2.2 定义配置类2.3 执行流程2.4 简化配置类到SpringMvcConfig中一. 概念 引入: 消息从浏览器发送到后端,请求会先到达Tocmat服务器&#x…...
轻松实现微信小程序上传多文件/图片到腾讯云对象存储COS(免费额度)
概述 对象存储(Cloud Object Storage,COS)是腾讯云提供的一种存储海量文件的分布式存储服务,用户可通过网络随时存储和查看数据。个人账户首次开通COS可以免费领取50GB 标准存储容量包6个月(180天)的额度。…...
Golang中defer和return的执行顺序 + 相关测试题(面试常考)
参考文章: 【Golang】defer陷阱和执行原理 GO语言defer和return 的执行顺序 深入理解Golang defer机制,直通面试 面试富途的时候,遇到了1.2的这个进阶问题,没回答出来。这种题简直是 噩梦\color{purple}{噩梦}噩梦,…...
谁说菜鸟不会数据分析,不用Python,不用代码也轻松搞定
作为一个菜鸟,你可能觉得数据分析就是做表格的,或者觉得搞个报表很简单。实际上,当前有规模的公司任何一个岗位如果没有数据分析的思维和能力,都会被淘汰,数据驱动分析是解决日常问题的重点方式。很多时候,…...
php mysql保健品购物商城系统
目 录 1 绪论 1 1.1 开发背景 1 1.2 研究的目的和意义 1 1.3 研究现状 2 2 开发技术介绍 2 2.1 B/S体系结构 2 2.2 PHP技术 3 2.3 MYSQL数据库 4 2.4 Apache 服务器 5 2.5 WAMP 5 2.6 系统对软硬件要求 6 …...
Vue3电商项目实战-首页模块6【22-首页主体-补充-vue动画、23-首页主体-面板骨架效果、4-首页主体-组件数据懒加载、25-首页主体-热门品牌】
文章目录22-首页主体-补充-vue动画23-首页主体-面板骨架效果24-首页主体-组件数据懒加载25-首页主体-热门品牌22-首页主体-补充-vue动画 目标: 知道vue中如何使用动画,知道Transition组件使用。 当vue中,显示隐藏,创建移除&#x…...
linux 使用
一、操作系统命令 1、版本命令:lsb_release -a 2、内核命令:cat /proc/version 二、debian与CentOS区别 debian德班和CentOS是Linux里两个著名的版本。两者的包管理方式不同。 debian安装软件是用apt(apt-get install),而CentOS是用yum de…...
基于遗传算法的微电网调度(风、光、蓄电池、微型燃气轮机)(Matlab代码实现)
💥💥💥💞💞💞欢迎来到本博客❤️❤️❤️💥💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清…...
方向导数与梯度下降
文章目录方向角与方向余弦方向角方向余弦方向导数定义性质梯度下降梯度下降法(Gradient descent)是一个一阶最优化算法,通常也称为最速下降法。 要使用梯度下降法找到一个函数的局部极小值,必须向函数上当前点对应梯度(…...
Java岗面试题--Java基础(日积月累,每日三题)
目录面试题一:Java中有哪些容器(集合类)?追问:Java中的容器,线程安全和线程不安全的分别有哪些?面试题二: HashMap 的实现原理/底层数据结构? JDK1.7 和 JDK1.8追问一&am…...
java基础—Volatile关键字详解
java基础—Volatile关键字详解 文章目录java基础—Volatile关键字详解并发编程的三大特性:volatile的作用是什么volatile如何保证有可见性volatile保证可见性在JMM层面原理volatile保证可见性在CPU层面原理可见性问题的例子volatile如何保证有序性单例模式使用volat…...
内存检测工具Sanitizers
Sanitizers介绍 Sanitizers 是谷歌开源的内存检测工具,包括AddressSanitizer、MemorySanitizer、ThreadSanitizer、LeakSanitizer。 Sanitizers是LLVM的一部分。 gcc4.8:支持Address和Thread Sanitizer。 gcc4.9:支持Leak Sanitizer和UBSani…...
Triton : OpenAI 开发的用于Gpu开发语言
Triton : OpenAI 开发的用于Gpu开发语言https://openai.com/blog/triton/1、介绍 https://openai.com/blog/triton/ 2、git地址 https://github.com/openai/triton 3、论文 http://www.eecs.harvard.edu/~htk/publication/2019-mapl-tillet-kung-cox.pdf SIMD : Single Inst…...
Python文件操作-代码案例
文章目录文件打开文件open写文件上下文管理器第三方库简单应用案例使用python生成二维码使用python操作excel程序员鼓励师学生管理系统文件 变量就在内存中,文件在硬盘中. 内存空间更小,访问速度快,成本贵,数据容易丢失,硬盘空间大,访问慢,偏移,持久化存储. \\在才是 \的含义…...
政府网站建设专题的目的/免费发外链
上一期我对BBR进行修改的目标很简单,就是提高算法的RTT公平性,主要修改点有3个: 固定增益系数改为了RTT的减函数。RTT相关的steady phase改为了固定时间。探测到带宽腾出时,马上进行up probe。 详情参见: https://zh…...
电影资源分享网站怎么做的/抖来查关键词搜索排名
权限管理权限表:1 订单管理2 用户管理3 菜单管理4 权限分配5 Bug管理用户表:1 Alex2 egon用户权限关系表:1 11 22 1import pymysqlclass DB:__conn pymysql.connect(host"localhost", user"root"…...
小购物网站建设/网店运营流程步骤
2019独角兽企业重金招聘Python工程师标准>>> 按照gdal预编译库sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable sudo apt-get update sudo apt-get install libgdal20按照python绑定pip install gdal如果在python console中使用import gdal出现sqlite3_c…...
网站建设算行政工作吗/企业如何网络推广
输入输出参数: 给存储过程传参数,叫做输入参数,用户告诉存储过程需要 利用这个参数干些什么. 输出参数: 从存储过程得到那些数据. 创建一个可选参数的存储过程: create proc pa1 name varchar(50)NULL as if(name is not null)select * from a where name like name%; elsesele…...
网站里自已的微信联系如何做/seo教程seo优化
举例:将i a b * c作为源代码输入到解析器里,则广义上的解析器的工作流程如下图: 发表时间:2009-10-17 最后修改:2011-03-04 < > 猎头职位: 上海: Senior Software Engine…...
可以做h5的网站有哪些/网站优化策略分析论文
写在前面 本文一起看下redis作为分布式锁使用的相关内容。 1:怎么算是锁或没锁 锁和没锁本身其实就是用一个变量的值来表示,比如变量lock,当值为1时代表处于上锁状态,当值为0时表示没有锁,那么多线程想要获取锁的话就…...