构造函数和析构函数
1构造函数是什么?
含义:
构造函数:对对象初始化的时候进行初始化。
析构函数:对象生命周期结束时进行清理工作。
2什么是初始化、赋初值?
初始化不是赋值,初始化的含义是创建变量的时候赋予其一个初始值,而赋值的含义是把对象的当前值擦去,用一个新值来代替
#include<bit/stdc++.h>
using namespace std;
int main()
{
sync_with_stdio(false);
int a=1;//这是进行初始化
a=8;//这时进行赋值操作
3给对象的数据成员赋值(public)
(1)用非构造函数赋值,此时对象所占空间已经完成分配。
(2)利用构造函数完成赋值,分配时同时进行初始化。
class Coord {
public:
void setCoord(int a,int b)
{ x=a; y=b; }
int getx()
{ return x; }
int gety()
{ return y; }
private:
int x,y;
};
void main()
{ Coord op1;//定义一个对像
int i,j;
op1.setCoord(5,6); // 调用op1的setCoord(),初始化对象op1
op1.setCoord(15,26); }
构造函数通常是对成员变量进行初始化
定义:
类名::类名(参数表)//函数名与类名一致。
{
}
默认构造函数:
类中没有定义构造函数,系统自动生成一个默认构造函数
类名::类名(){} //空函数
拷贝构造函数(复制构造函数)
使用一个已经创建完毕的对象来初始化一个新的同类型对象。其实使用复制构造函数时都会创建一个临时变量,拷贝构造函数把对象放在一个一个临时变量
object::object(const object &p){}
//基本格式
参数是本类型的一个引用变量
当函数具有类类型传值参数和返回类类型时都需要调用复制构造函数
(1)当一个类作为值传递方式给函数参数传值时调用构造函数
(2)当用实参初始化一个形参的时候
(3)指针时只可以复制地址而不可以复制值
- 默认拷贝构造函数
这个执行浅拷贝***
很多时候在我们都不创建拷贝构造函数的情况下,传递对象给函数参数或者函数返回对象都能很好的进行,这是因为编译器会给我们自动产生一个拷贝构造函数,这就是“默认拷贝构造函数”
(也就是说一般情况下传值返回对象都会自己默认创建一个)
深复制
浅复制与深复制区别大概就是存在于指针方面,我们都知道,使用指针时复制的都是地址而不是数值,浅拷贝只是简单的复制了一下数据成员,但一遇到堆栈问题就显得捉襟见肘,使用浅复制时把两个指针指向了同一个堆空间。这就在进行析构时对这个空间进行了两次析构产生释放“释放空指针”的错误
还有说一下,拷贝构造函数本质上还是一个构造函数所以可以调用类中的任意成员。
#include<iostrean>
#include<cstring>
using namespace std;
struct Date{
int year,month,day;}
class Student{
public:
Student]
构造函数的重载:
在一个类中可以定义多个构造函数,以便提供不同的初始化。这些构造函数具有相同的函数名,而参数的个数或参数的类型不相同。这称为构造函数的重载。
创建对象时要知道如果没有显示参数类型和个数会自动调用默认构造函数
Box(){
…
}
Box(int i=10,int j=30, int k=40){
…
}
这里可以看做四个重载函数
构造函数的初始化列表进行初始化
与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段。另外初始化优先。
class Date
{
int d,m,y;
poublic:
Date(int d1,int m1,int y1):d(d1),m(m1),y(y1);//就是在这里对它进行初始化。
}
为啥子使用初始化列表:
使用初始化列表少了一次调用默认构造函数的过程,大大的提高了运行的效率。其实列表和构造函数差不多,但是还是有必须使用参数初始化列表对数据成员进行初始化的时候
几种情况
(1)数据成员为常量
(2)引用
(3)对象
class Coord {
public:
Coord(int y,int y2):x(y),x1(y2),x3(3)//参数初始化列表
{}
void()
{}
private:
int x,&x1;
const int x3;
}
这里对数据成员进行初始化的顺序依照函数声明来规定,与初始化类表出现的顺序无关。