当前位置:网站首页>构造函数,拷贝函数和析构函数的区别
构造函数,拷贝函数和析构函数的区别
2022-07-26 22:45:00 【江南伯爵.】
默认函数
因为c++主要是为了面向对象,所以具有三大基本特征:封装,继承,多态,而c++的类中六个默认函数便主要是为了封装的过程,即:构造函数,拷贝函数,析构函数,赋值操作数的重载,取地址操作符的重载,const修饰的取地址操作符重载
这里主要讲构造函数,拷贝函数,析构函数的区别
构造函数
构造函数的函数名称必须与类名同名,并且构造函数没有返回值,构造函数的主要功能是为了初始化函数
class A {
public:
A(int a,int b,char c) {
_a = a;
_b = b;
_c = c;
}
int _a;
int _b;
char _c;
};
int main() {
A i(1,2,'s');
cout << i._a << i._b << i._c << endl;
return 0;
}
我们观察上面代码,可以看到我们定义了一个类类型A,在主函数创建了对象i,并把1,2,s的数据传输给了_a,_b,_c成员变量,而类中A函数便是构造函数。我们要注意是,类中_a,_b,_c变量仅仅只是声明对象,并没有开辟空间创建对象,他们是在构造函数A中初始化对象的
那如果我们不创建构造函数,能否成功呢?
答案是可以,因为编译器会自带默认构造函数,默认构造函数即编译器自动初始化函数
class A {
public:
int _a=1;
int _b=2;
char _c='s';
int main() {
A i;
cout << i._a << i._b << i._c << endl;
return 0;
};
这里便是直接进行默认构造函数的初始化,上面代码的输出同样也是12s,不过我们可以用更方便的缺省构造函数,这个同样也是默认构造函数
class A {
public:
A(int a = 1, int b = 2, char c = 's') {//缺省构造函数
_a = a;
_b = b;
_c = c;
}
int _a;
int _b;
char _c;
};
int main() {
A i1(3,4,'t');
A i2;
cout << i1._a << i1._b << i1._c << endl;
cout << i2._a << i2._b << i2._c << endl;
return 0;
}
上面代码输出是34t和12s,进行传参时则使用传参值,没有传参则默认初始化
值得注意的是,在我们没有写构造函数时,编译器默认构造函数会有一个偏心处理:
1、内置类型不进行初始化 2、而自定义类型则会调用他的构造函数初始化,若自定义类型没有构造函数,则同样也不会进行初始化
析构函数
析构函数没有返回值,没有参数,析构名在类名前面加一个~,若类未定义,则编译器会自动生成默认的析构函数,在对象生命周期结束时,会自动调用析构函数
析构函数的主要作用是为了释放如malloc在堆上面开辟内存空间的对象,进行清理
class Stack {
public:
Stack(int capacity = 4) {
_a = (int*)malloc(sizeof(int) * capacity);
if (_a == nullptr) {
cout << "malloc fail" << endl;
exit(-1);
}
_top = _capacity = 0;
}
~Stack() {
free(_a);
_a = nullptr;
_top = _capacity = 0;
}
int* _a;
int _top;
int _capacity;
};
int main() {
Stack i;
return 0;
}
拷贝函数
没有返回值,以类名作为函数名
class A {
public:
A(int a = 1, int b = 2, char c = 's') {
_a = a;
_b = b;
_c = c;
}
A(const A& d) {
//拷贝函数
_a = d._a;
_b = d._b;
_c = d._c;
}
int _a;
int _b;
char _c;
};
int main() {
A i;
A i2(i);//A i2=i;同样调用拷贝函数
cout << i2._a << i2._b << i2._c << endl;
return 0;
}
经过调试后,我们可以发现A i2(i);这里的代码调用了拷贝函数值得注意的是,这里拷贝函数的传参传的是引用,意味着d是类A的i的引用,若没有引用,那么会导致我拷贝函数里定义d也要拷贝函数,这会形成一个传值无穷递归的问题,所以需要加一个&,来进行引用
如果引用传参,不是做输出型参数,最好用const &来做保护(即内部成员变量不会改变)
注:在对于函数内的类的传值传参,还有返回值都是要调用拷贝构造的
对于编译器自动生成的拷贝函数,不会去区分内置类型和自定义类型,都会处理
1、内置类型,字节序的浅拷贝
2、自定义类型,会去调用他的拷贝构造
但由于是浅拷贝,对于自己开辟内存单元的(如上面的Stack)则难以实现默认拷贝构造,会生成崩溃
int main(){
Stack st1;
Stack st2(st1);
return 0;
}
上面代码就会崩溃,因为st1和st2在堆中生成空间,先创建st1,再创建st2,在进行析构函数时,先对st2的_a进行释放空间,轮到st1时候,因为_a的空间已经释放过,则无妨二次释放,所以到导致程序崩溃
总结
| 函数 | 功能 |
|---|---|
| 构造函数 | 初始化对象 |
| 拷贝函数 | 对对象进行拷贝 |
| 析构函数 | 释放堆上开辟的空间 |
以上便是构造函数,拷贝函数和析构函数的区别了
边栏推荐
猜你喜欢

ESP8266 STA_ TCP_ Server

ESP8266 AP_ TCP_ Server
![[question] what if Yum resources are occupied](/img/8d/50129fa1b1ef0aa0e968e6e6f20969.png)
[question] what if Yum resources are occupied

Traversing binary trees in non recursive pre -, middle -, and post order

Finding the greatest common divisor

Software Foundation of software test interview questions

标准C库的IO函数

【Oracle】获取最近工作日及前N个工作日

LAMP.

EXPECT免交互
随机推荐
GDB的使用
Web services (07) - LNMP one click deployment
Web服务器(01)——介绍web服务器
iptables防火墙(二)
十五、expect
Jenkins -- Basic -- 03 -- post installation setup wizard
Excel changes the format of scientific counting method into text
进程与计划任务管理
Pyqt5 qtablewidget setting gives priority to the text on the right
C language to realize mine sweeping game:
Iptables firewall (II)
7、 Loop statement
Longest substring without duplicate characters
Problem feedback: the synchronization of mobile app failed: the external changes of the data warehouse were damaged. The iPad app also downloaded the warehouse as soon as it was opened, and then flash
Understanding and learning of internal classes
十三、命令小工具
15、 Expect
PHP exit codes description
Buuctf casual note, exec, easysql, secret file
ESP8266 AP_ MODE