网站支付页面设计/常用的网络营销推广方法有哪些
文章目录
- 什么是面向对象?
- 一:类是什么?
- 1.类的访问限定符
- 2.封装
- 3.类的实例化
- 4.this指针
- 二:类的6个默认成员函数
- 1.构造函数
- 2.析构函数
- 3.拷贝构造函数
什么是面向对象?
c语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
比如洗衣服:
c++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
在C语言中很多的过程在c++中被分为了人 衣服 洗衣机 洗衣粉,想要完成洗衣粉这件事只需要人将衣服放进洗衣机,倒入洗衣粉,启动洗衣机就完成了。
一、类是什么?
C语言结构体中只能定义变量,在c++中结构体内不仅可以定义变量,也可以定义函数。比如:之前我们用C语言方式实现的栈,结构体中只能定义变量,现在以c++的方式实现,会发现struct中也可以定义函数。
struct Stack
{void Init(int n = 4){a = (int*)malloc(sizeof(int) * n);if (nullptr == a){perror("malloc申请空间失败");return;}capcity = n;top = 0;}void Push(int x){}void Pop(){}int Top(){}bool Empty(){}int* a;int capcity;int top;
};
int main()
{Stack st;st.Init();st.Push(1);st.Push(2);st.Push(3);return 0;
}
就像上面的代码段一样,以前C语言是不支持将函数写入结构体的,而c++现在能做到了。
而上面的struct在c++中更喜欢用class来代替。
那么怎么创建一个类呢?看下面代码段:
class classname // class后面跟你自己想要取的类名
{//类体,由成员函数和成员变量组成
}; //后面一定要加;和结构体一样
class为定义类的关键字,classname为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。类体中的内容称为类的成员,类中的变量称为类的属性或成员变量,类中的函数称为类的方法或者成员函数。类中定义的变量都可以直接在类中使用,类外则需要域限定符。
类的两种定义方式:
1.声明和定义全部放在类体中,需要注意的是,成员函数如果在类中定义,编译器可能会当成内联函数来处理。比如下面这样的:
class classname
{
public:void add(){year++;}
private :int year;
};
2.类声明放在头文件中,成员函数的定义放在.cpp文件中。
class classname
{
public:void add();
private :int year;
};
void classname::add()
{year++;
}
类的访问限定符:
c++中有三种访问限定符,分为public(公有),private(私有)私有的在类外不可以访问,protected(受保护的)同样在类外不可以访问。
c++实现封装的方式:用类将对象的属性和方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
1.pubic修饰的成员在类外可以直接被访问
2.protected和private修饰的成员在类外不能直接被访问
3.访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。
4.如果后面没有访问限定符,作用域到 } 及类结束。
5.class的默认访问权限为private,struct的默认访问权限为public(因为要兼容C语言)
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别。
class Date
{
public:void Init(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;d1.Init(2023,2,5);d1.Print();return 0;
}
大家觉得上面这个代码段可以成功打印出年月日吗?答案是不可以,因为我们在private中定义的年与Init函数传来的参数year一样,这就导致编译器识别不出来,所以我们在定义成员变量的时候最好都像month那样在前面加个符号用来区分。
封装 :
面向对象的三大特性:封装,继承,多态。
封装的意思就是将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。封装的本质就是一种管理,让用户更方便的使用类。举个例子:就像电脑的主机一样,主机只提供开机键等接口,而实际上电脑真正工作的东西是cpu等硬件,而这些硬件是不会暴露在外边让用户看到的。
类的实例化:
用类的类型创建对象的过程,称为类的实例化。类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它,比如以下代码:
我们已经说过类是对对象进行描述的,只有创建了一个类对象,才会给这个类对象分配空间,这样就可以使用类里面的函数等变量。下图为正确的使用方式:
下面我们来看类中成员如何存储的:
class Date
{
public:void Init(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;cout << sizeof(d1) << endl;return 0;
}
大家可以猜一猜d1这个对象的大小是多少?答案是12,12不就是private中三个成员变量的大小吗,为什么成员函数不占用空间呢?
大家看上图,d1的year变量和d2的year变量是在同一块空间吗?答案是不在同一块空间,因为对象实例化后会给每个对象都开辟一个空间,那么d1的year肯定是在d1这个对象开辟的空间内,d2的year是在d2这个对象开辟的空间内。
那么 d1的init函数和d2的init函数是在同一块空间吗?答案是是的,c++中为了防止每个对象都开辟空间存储不同的函数所以将函数放在了公共的代码段,想要调用这个函数直接去公共的代码段去找即可,这也就解释了为什么我们再计算对象的大小的时候不包含函数的大小了。至于为什么成员变量不设为公共的问题就很好回答了,应该每个对象都能对自己的成员变量进行修改,如果设为一个公共的那么d2对象修改year的值也会将d1对象的year进行修改。
// 类中既有成员变量,又有成员函数
class A1 {
public:void f1() {}
private:int _a;
};// 类中仅有成员函数
class A2 {
public:void f2() {}
};// 类中什么都没有---空类
class A3
{};
上面这三个类的sizeof大小是多少呢?
有了上面的解释回答这道题就很容易了,首先A1中只有变量_a占实际空间,所以大小为4字节。
A2中只有成员函数,而成员函数在代码段中那么这个A2就相当于A3是一个空类,空类在c++中占一个字节。
this指针
class Date
{
public:void Init(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;Date d2;d1.Init(1, 2, 3);d2.Init(4, 5, 6);d1.Print();d2.Print();return 0;
}
对于上面的代码段,有这样一个问题:Date类中有Init和Print两个成员函数,函数体中没有关于不同对象的区分,那当d1调用Init函数时,该函数是如何知道设置d1对象,而不是设置d2对象呢?
对于这个问题,c++中引用了this指针来解决这个问题。即:c++编译器给每个"非静态的成员函数"增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有"成员变量"的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需用来传递,编译器自动完成。比如下面代码:
class Date
{
public:void Init(int year, int month, int day)//用户看到的//实际上 void Init(Date* this,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;Date d2;d1.Init(1, 2, 3);//用户看到的//实际上//d1.Init(&d1, 1, 2, 3);d2.Init(4, 5, 6);d1.Print();d2.Print();return 0;
}
在这里要注意,我们不能显式的自己去调用的时候传入对象的地址,这样编译器会报错。
那么this指针有什么作用呢?
class Date
{
public:void Init(int year, int month, int day){this->year = year;this->month = month;this->day = day;cout << this << endl;}void Print(){cout << year << "年" << month << "月" << day << "日" << endl;}
private:int year; ///这些只是声明并不是定义int month;int day;
};int main()
{Date d1;Date d2;d1.Init(1, 2, 3);d2.Init(4, 5, 6);d1.Print();d2.Print();return 0;
}
之前Init函数中不能分辨的year等变量用上this指针就可以正确分辨,还可以打印此对象的地址
那么this指针存放在哪里呢?this指针存放在栈中,因为this是隐含形参/vs下面是存在ecx寄存器中
this指针可以为空吗?看以下代码:
class Date
{
public:void Init(int year, int month, int day){this->year = year;this->month = month;this->day = day;cout << this << endl;}void Print(){cout << year << "年" << month << "月" << day << "日" << endl;}void Func(){cout << "Func()" << endl;}
private:int year; ///这些只是声明并不是定义int month;int day;
};int main()
{Date* ptr = nullptr;ptr->Func();return 0;
}
上面这段代码可以正常编译吗?很多人看到ptr是个空指针然后去调用Func函数会觉得这里对空指针进行解引用了,这样理解其实是不对的,首先这个代码可以正常编译看下图:
这里解释一下为什么可以编译,我们之前说过调用类中的函数时编译器会隐式修改为传对象的地址然后函数多了一个this指针的参数,所以当我们调用func这个函数的时候,编译器通过this指针找到了类中的这个函数即使把ptr这个空指针传给了this,也是可以正常使用的。那么下面这个程序的运行结果又是怎么样的?
上图这段代码运行起来程序崩溃了,首先这个Init和刚刚的func函数一样都不在对象里面,他们都在公共区域,调用这个函数直接跳到存放代码的地址,这些都没问题,有问题的是ptr是空指针,ptr给this传了个空指针然后再Init函数中这个空指针指向Year这个变量,这就是对空指针进行解引用了。
那么上图中这个代码是否可以正常运行呢?很多人看到括号内对ptr空指针进行解引用了以为程序会崩溃,但其实并不是,编译器还是先去对象里找有没有Func()这个函数,然后编译器发现找不到通过this指针找到了Func函数的公共代码段,而这里的(ptr)是起到了给传给this指针的作用。
那么上图中的这个代码运行起来会不会崩溃呢? 这个一定是崩溃了,编译器先去找year是不是在对象里,找到后发现这个对象有自己的空间所以对空指针进行解引用了。通过上面几个问题大家应该知道this指针是可以为空的了。
二、类的默认6个成员函数
如果一个类中什么成员都没有,简称为空类。空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数,默认成员函数:用户没有显式实现,编译器会生成的函数称为默认成员函数。
构造函数主要完成初始化工作
析构函数主要完成清理工作
拷贝构造是使用同类对象初始化创建对象
赋值重载主要是把一个对象赋值给另一个对象
完成取地址重载的两个函数很少会自己实现所以就不在讲解
构造函数
构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有一个合适的初始值,并且在对象整个生命周期内只调用一次。
构造函数的特性:1.函数名与类名相同
2.无返回值
3.对象实例化时编译器自动调用对应的构造函数
4.构造函数可以重载
class Stack
{
public:Stack(int capcity = 0,int top = 0){_capcity = capcity;_top = top;}void Print(){cout << "_capcity:" << _capcity << endl;cout << "_top:" << _top << endl;}
private:int* a;int _capcity;int _top;
};
int main()
{Stack st;Stack st1(10, 4);st.Print();st1.Print();return 0;
}
无参构造函数和带参构造函数的调用方式是不一样的,上面的代码我们在构造函数中用了缺省值的方式,必须要说明的是无参构造函数直接Stack st;即可,也就是说对象实例化创建后就会调用,而带参的构造函数必须在后面加括号写入参数入上图中st1一样。
需要注意的是:
class Date
{
public:Date(){_year = 1;_month = 1;_day = 1;}Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}
public:int _year; int _month;int _day;
};int main()
{Date d1;d1.Print();return 0;
}
像上图中这样的情况,语法本身并没有问题,是因为编译器无法分清无参的构造函数和带缺省参数的构造函数,解决的方法为调用是以带参构造函数的方式去调用。
我们之前已经说过,在实例化对象的时候必须调用构造函数,如果我们不写编译器会给一个默认的构造函数,那么我们就看看默认的构造函数可以完成对象的初始化吗
class Date
{
public:void Print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}
public:int _year; int _month;int _day;
};int main()
{Date d1;d1.Print();return 0;
}
可以看到我们是没有写构造函数的。
当我们调用的时候发现好像编译器默认的构造函数好像并不能完成初始化,这是怎么回事呢?这是因为c++把类型分为内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如int/char...等,自定义类型就是我们使用class/struct/union等自己定义的类型,而编译器生成的默认构造函数会对自定义类型成员调用它的默认成员函数。
也就是说默认生成的构造函数,对内置类型成员不做处理。自定义类型成员会去调用它的默认构造(不用传参数的构造)
class MyQueue
{
public://默认生成的构造函数对自定义类型,会调用它的默认构造函数void Push(int x){}Stack _pushST;Stack _popST;
};int main()
{MyQueue mq;return 0;
}
从上图中我们发现默认构造函数对于自定义类型会进行初始化 。析构函数作为专门初始化的函数大多人都认为应该将内置类型也初始化了而不是只针对自定义类型,针对这个问题在c++11中打入了一个补丁,就是可以直接给内置类型变量一个缺省值,什么意思呢?看下面代码:
class Date
{
public:void Print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}
public:int _year = 1; int _month = 1;int _day = 1;
};int main()
{Date d1;d1.Print();return 0;
}
通过这个补丁就能解决内置类型初始化的问题了。
析构函数
与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的,而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。
析构函数的特性:1.析构函数是在类名前加上~
2.无参数无返回值类型
3.一个类只能有一个析构函数,若未显式定义,系统会自动生成默认的析构函 数。注意:析构函数不能重载。
4.对象生命周期结束时,c++编译系统系统自动调用析构函数
class Stack
{
public:Stack(int capcity = 0,int top = 0){_capcity = capcity;_top = top;}void Print(){cout << "_capcity:" << _capcity << endl;cout << "_top:" << _top << endl;}~Stack(){cout << "这是析构函数" << endl;}
private:int* a;int _capcity;int _top;
};
int main()
{Stack st;Stack st1(10, 4);st.Print();st1.Print();return 0;
}
我们在return处打了一个断点然后F5跳到断点处F11进入函数发现进入到了析构函数中并且打印了
默认生成的析构函数与默认生成的构造函数一样,对内置类型成员不做处理。自定义类型成员会去调用它的默认析构函数。析构函数的调用遵循后进先出原则,也就是说后定义的对象先进行析构函数的调用。
class Time
{
public:Time(){cout << "Time()" << endl;}~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;
}
在main中根本没有创建Time类的对象,但还是打印了Time和~Time,可见析构函数确实会对自定义类型调用其自己的析构函数。(构造函数同理)
拷贝构造函数
只有单个形参,该形参是本类类对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
1.拷贝构造函数是构造函数的一个重载形式 以下是拷贝构造函数实例:
class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}void Print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}
public:int _year ; int _month ;int _day ;
};int main()
{Date d1;Date d2(d1); //调用拷贝构造函数d1.Print();d2.Print();return 0;
}
我们可以看到d2确实和d1的参数是一样的说明拷贝成功了。
const修饰能起到什么作用呢?我们都知道加const修饰就是为了不被修改,看以下代码:
这里加const其实是为了防止将谁是谁的拷贝的位置写错了,一旦写错不加const那么用来拷贝的那个类里面的东西都被修改了。
当然用const修饰还有第二个好处,那就是防止权限的放大。
就如图中我们定义了一个const的对象,再调用拷贝构造时发现报错了,原因是d1本来是const this*,到了拷贝构造函数中变成了this*权限放大了,想要解决在拷贝构造的函数参数中加上const即可。
2.拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
为什么会引发无穷递归调用呢,那是因为我们在传值传参的时候只要是自定义类型那么编译器会自动调用拷贝构造函数,举个例子:Date(Date d)如果这是拷贝构造函数,在调用这个函数的时候发现参数为自定义的Date类型那么就会调用拷贝构造函数又出现了Date(Date d)然后一直无穷递归下去,而使用引用为什么会避免呢?因为引用就是他本身再调用也是他本身不会再去调用新的拷贝构造函数。那么为什么编译器不能去拷贝自定义类型呢?
想要解决这样的问题就直接在拷贝构造函数中重新给要拷贝的对象开和被拷贝对象同样的空间,这样他们两个的地址不同在释放内存的时候就不会崩溃了。
3.日期类不需要写拷贝构造,因为内置类型编译器也会处理。
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;Date d2(d1);d2.print();return 0;
}
通过上面的代码我们可以发现即使我们不写拷贝构造函数编译器也能完成日期类的拷贝,那么自定义类型可以吗?
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){cout << "Stack(size_t capacity = 10)" << endl;_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");exit(-1);}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){cout << "~Stack()" << endl;if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType *_array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;Stack s2(s1);return 0;
}
我们以栈为例,运行后发现程序崩溃了,这是因为编译器默认的拷贝方式是浅拷贝这里我们在上面已经讲过这个拿图来看:
我们调试发现确实两个栈的地址是一样的,所以在析构函数释放空间的时候两个对象释放两次导致崩溃了。解决方式如下:
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){cout << "Stack(size_t capacity = 10)" << endl;_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");exit(-1);}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}Stack(const Stack& s){_array = (DataType*)malloc(sizeof(DataType) * s._capacity);if (_array == nullptr){perror("malloc:");exit(-1);}memcpy(_array, s._array, sizeof(DataType) * s._size);_capacity = s._capacity;_size = s._size;}~Stack(){cout << "~Stack()" << endl;if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType *_array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;Stack s2(s1);return 0;
}
通过上面这个例子我们能得出结论,对于内置类型编译器的默认拷贝构造函数可以通过浅拷贝完成拷贝,但是像栈这样的自定义类型默认的拷贝构造函数不仅无法正确拷贝还会引发错误。
那么什么情况下需要自己写拷贝构造呢?
结论:自己实现了析构函数释放空间,就需要实现拷贝构造。
那么下面这样的代码需要自己写拷贝构造吗?
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){cout << "Stack(size_t capacity = 10)" << endl;_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");exit(-1);}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}Stack(const Stack& s){_array = (DataType*)malloc(sizeof(DataType) * s._capacity);if (_array == nullptr){perror("malloc:");exit(-1);}memcpy(_array, s._array, sizeof(DataType) * s._size);_capacity = s._capacity;_size = s._size;}~Stack(){cout << "~Stack()" << endl;if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType *_array;size_t _size;size_t _capacity;
};
class MyQueue
{
public:// 默认生成构造// 默认生成析构// 默认生成拷贝构造
private:Stack _pushST;Stack _popST;int _size = 0;
};int main()
{MyQueue q1;MyQueue q2(q1);return 0;
}
通过上图我们就知道了答案是不需要,因为自定义类型会去调用它自己的拷贝构造,而栈的拷贝构造我们已经实现了所以不需要。
什么情况下会调用拷贝构造呢?1.显式调用(就是自己要去时候拷贝构造) 2.传值传参(比如参数是自定义类型) 3.自定义类型做返回值 。
所以为了减少空间的消耗那么能用引用尽量去用引用。
总结
c++初学者对于学习构造函数,拷贝构造,析构函数是一大难点,所以想要真正的了解必须多练习多调试多思考,只有基础好了才能建高楼!
下一期是c++前期的重点运算符重载等的学习。
相关文章:

【c++】类和对象:让你明白“面向一个对象有多重要”:构造函数,析构函数,拷贝构造函数的深入学习
文章目录 什么是面向对象?一:类是什么? 1.类的访问限定符 2.封装 3.类的实例化 4.this指针二:类的6个默认成员函数 1.构造函数 2.析构函数 3.拷贝构造函数什么是面向对象? c语言是面向…...

职场IT老手教你3步教你玩转可视化大屏设计,让领导眼前一亮!
我是制造企业的IT中心的研发人员,平常工作就是配合业务部门出出报表,选型一些商业软件,并在内部负责实施运维。最近领导出去参观了一些数字化转型比较领先的工厂和制造企业,回来就甩给我几张图,问能不能我们也做几个这…...

【光伏功率预测】基于EMD-PCA-LSTM的光伏功率预测模型(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

大数据Kylin(二):Kylin安装使用
文章目录 Kylin安装使用 一、Kylin安装要求 二、Kylin安装 1、Kylin安装前环境准备...

我们的微服务中为什么需要网关?
说起 Spring Cloud Gateway 的使用场景,我相信很多小伙伴都能够脱口而出认证二字,确实,在网关中完成认证操作,确实是 Gateway 的重要使用场景之一,然而并不是唯一的使用场景。在微服务中使用网关的好处可太多了&#x…...

互联网医院源码 线上问诊 智慧医院源码 C#源码
互联网医院平台源码 智慧医院管理系统源码 开发环境:ASP.NET C# VS2019 SQL2008 依托于实体医院利用互联网技术对接院内业务信息系统,向患者提供基于线上问诊、预约挂号、缴费结算、医患互动、诊后随访、健康科普和复诊等全面的医疗健康互联网服务。…...

基于昇腾计算语言AscendCL开发AI推理应用
01 初始AscendCL AscendCL(Ascend Computing Language,昇腾计算语言)是昇腾计算开放编程框架,是对底层昇腾计算服务接口的封装,它提供运行时资源(例如设备、内存等)管理、模型加载与执行、算子…...

JS document.write()换行
换行效果: 通过传递多个参数,即可实现换行效果: document.write("<br>",ar) 效果: 示例源码: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&quo…...

Java高级-集合-Collection部分
本篇讲解java集合 集合 集合框架的概述 集合、数组都是对多个数据进行存储操作的结构,简称Java容器。 说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库中…...

Android性能优化:getResources()与Binder交火导致的界面卡顿优化
欢迎:https://juejin.cn/post/7198430801851531324/ 欢迎:https://nasdaqgodzilla.github.io/2023/02/10/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%EF%BC%9AgetResources-%E4%B8%8EBinder%E4%BA%A4%E7%81%AB%E5%AF%BC%E8%87%B4%E7%9A%84%E7%95%8C%E…...

常见的内存操作函数
👦个人主页:Weraphael ✍🏻作者简介:目前是C语言学习者 ✈️专栏:C语言航路 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬 点赞&a…...

python关键字
文章目录1 and、or、not2 if、elif、else3 for、while4 True、False5 continue、break6 pass7 try、except、finally、raise8 import、from、as9 def、return10 class11 lambda12 del13 global、nonlocal14 in、is15 None16 assert17 with18 yield1 and、or、not and、or、not…...

C语言 | 预处理知识详解 #预处理指令有哪些?他们如何使用?宏和函数有哪些区别?...#
文章目录前言预定义符号介绍预处理指令#define#define替换规则预处理指令 #undef宏和函数的对比宏和函数的对比图命名约定命令行定义条件编译预处理指令 #include嵌套文件包含其他预处理指令写在最后前言 上篇文章介绍了一个程序运行的 编译与链接 ,其中编译阶段有个…...

如何实现LFU缓存(最近最少频率使用)
目录 1.什么是LFU缓存? 2.LFU的使用场景有哪些? 3.LFU缓存的实现方式有哪些? 4.put/get 函数实现具体功能 1.什么是LFU缓存? LFU缓存是一个具有指定大小的缓存,随着添加元素的增加,达到容量的上限&…...

【C++之容器篇】精华:vector常见函数的接口的熟悉与使用
目录前言一、认识vector1. 介绍2. 成员类型二、默认成员函数(Member functions)1. 构造函数2. 拷贝构造函数vector (const vector& x);3. 析构函数4. 赋值运算符重载函数三、迭代器(Iterators)1. 普通对象的迭代器2. const对象…...

InstructGPT
文章目录Abstract 给定人类的命令,并且用人工标注想要的结果,构成数据集,使用监督学习来微调GPT-3。 然后,我们对模型输出进行排名,构成新的数据集,我们利用强化学习来进一步微调这个监督模型。 我们把产…...

RTOS之一环境搭建(基于TM4C123GXL)
硬件TM4C123GXLBOOSTXL-EDUMKII keil5micriumOSA软件安装:1 ARM-MDK(MDK538aMDK_Stellaris_ICDI_AddOn)MDK538a链接:https://www.keil.com/demo/eval/arm.htmICDI链接:https://documentation-service.arm.com/static/60509bd61da8f8344a2ca1b…...

151、【动态规划】AcWing ——2. 01背包问题:二维数组+一维数组(C++版本)
题目描述 原题链接:2. 01背包问题 解题思路 (1)二维dp数组 动态规划五步曲: (1)dp[i][j]的含义: 容量为j时,从物品1-物品i中取物品,可达到的最大价值 (2…...

DS期末复习卷(二)
选择题 1.下面关于线性表的叙述错误的是( D )。 (A) 线性表采用顺序存储必须占用一片连续的存储空间 (B) 线性表采用链式存储不必占用一片连续的存储空间 © 线性表采用链式存储便于插入和删除操作的实现 (D) 线性表采用顺序存储便于插…...

大数据技术架构(组件)31——Spark:Optimize--->JVM On Compute
2.1.9.4、Optimize--->JVM On Compute首要的一个问题就是GC,那么先来了解下其原理:1、内存管理其实就是对象的管理,包括对象的分配和释放,如果显式的释放对象,只要把该对象赋值为null,即该对象变为不可达.GC将负责回…...

ETL基础概念及要求详解
ETL基础概念及要求详解概念ETL与ELT数据湖与数据仓库ETL应用场景ETL具体流程及操作要求抽取清洗转换加载ETL设计模式SQL脚本语言ETL工具设计ETL工具SQLETL接口设计要求明确接口属性约定接口形式确定接口抽取方法规范接口格式概念 ETL即Extract(抽取)Tra…...

刷题记录:牛客NC23054华华开始学信息学 线段树+分块
传送门:牛客 题目描述: 题目latex公式较多,此处省略 输入: 10 6 1 1 1 2 4 6 1 3 2 2 5 7 1 6 10 2 1 10 输出: 3 5 26这道题让我体验到的线段树相对于树状数组的常数巨大 我们倘若直接用单点修改的话,如果D过小比如1那么我们足足要加n次,时间复杂度爆…...

二叉搜索树(查找,插入,删除)
目录 1.概念 2.性质 3.二叉搜索树的操作 1.查找 2.插入 3.删除(难点) 1.概念 二叉搜索树又称二叉排序树.利用中序遍历它就是一个有顺序的一组数. 2.性质 1.若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 2.若它的右子树不为空,则右子树上所有节点的值都…...

C# PictureEdit 加载图片
方法一: 如果要加载的图片的长宽比不是太过失衡, 1.可以改变picturebox的SizeMode属性为 PictureBoxSizeMode.StretchImage, 2.或者Dev控件 PictureEdit的SizeMode属性为Zoom。(zoom:缩放;clip剪短;stret…...

3种方法设置PDF“打开密码”,总有一种适合你
PDF文件是我们工作中经常用到的文件之一,对于重要的文件,设置“打开密码”是一种很好的保护方式。下面就来说说,设置PDF“打开密码”有哪三种方法? 方法一:在线网站加密 市面上有很多可以直接在线上加密PDF文件的产品…...

第三章 数据链路层(点到点的传输服务)-计算机网络(笔记)
计算机网络 第三章 数据链路层(点到点的传输服务) 数据链路层属于计算机网络的低层。数据链路层使用的信道主要有以下两种类型: (1)点到点信道。这种信道使用一对一的点到点通信方式。 (2)广…...

volatile关键字与CAS机制
volatile关键字 volatile关键字可以对类的成员变量与静态变量进行修饰 volatile关键字的作用 1.保证被修饰属性的可见性,被修饰后的属性如果被更改后其他线程是会立即可见的 2.保证被修饰属性的有序性,被修饰后的属性禁止修改指令执行的顺序 注意:volatile关键字不能保证属性…...

LeetCode题解 动态规划(四):416 分割等和子集;1049 最后一块石头的重量 II
背包问题 下图将背包问题做了分类 其中之重点,是01背包,即一堆物件选哪样不选哪样放入背包里。难度在于,以前的状态转移,多只用考虑一个变量,比如爬楼梯的阶层,路径点的选择,这也是能用滚动数组…...

【FFMPEG源码分析】从ffplay源码摸清ffmpeg框架(二)
demux模块 从前面一篇文章中可以得知,demux模块的使用方法大致如下: 分配AVFormatContext通过avformat_open_input(…)传入AVFormatContext指针和文件路径,启动demux通过av_read_frame(…) 从AVFormatContext中读取demux后的audio/video/subtitle数据包…...

PCIE 学习笔记(入门简介)
PCIE 学习笔记书到用时方恨少啊,一年前学PCIE的笔记,再拿出来瞅瞅。发到博客上,方便看。PCIE基础PCIE和PCI的不同PCIE采用差分信号传输,并且是dual-simplex传输——每条lane上有TX通道和RX通道,所以每条lane上的信号是…...