构造函数和析构函数
每日文摘
我感冒了 ,因为我对你没有抵抗力。
构造函数和析构函数
注意:程序会在对象销毁前自动调用析构函数
1.析构函数通常作用是将在堆区开辟的内存释放
2.函数先执行的后析构
一. 构造参数的分类
按有参无参分为 :有参构造和无参构造
按类型分:普通构造和拷贝构造
class stu {
public:
//无参构造
stu() {
cout << "无参构造" << endl;
}
//有参构造
stu(int p) {
cout << "有参构造" << endl;
}
//拷贝构造
stu(const stu &p) {
cout << "拷贝构造构造" << endl;
}
~stu() {
cout << "析构函数" << endl;
}
};
反过来了
二. 构造函数的调用
方法:
1.括号法(常用)
stu p;//无参构造
stu p1(10);//有参构造
stu p2(p1);//拷贝构造
注意点:无参构造不能写成这种 stu p() 构造器会认为这是函数的声明
2.显试法
stu p1 = stu (10);//有参
stu p2 = stu(p2);//拷贝
注意 stu(10)单独写就是匿名对象,当前结束后马上析构
3.隐试法
stu p1 = 10;//stu p1=stu(10)
stu p2 = p1;//stu p2=stu(p1)
构造函数的调用规则
1.在默认情况下,编译器会至少给一个类提供三个函数
默认的构造参数无参,函数体为空
默认的析构函数无参,函数体为空
默认的拷贝构造函数,对属性进行值拷贝
2.
2.1 如果用户定义了有参构造函数,编译器将不会定义默认无参构造函数,但会定义拷贝构造函数
2.2 如果用户定义了拷贝构造函数,编译器将不会定义任何构造函数
三.拷贝函数调用的时机
1.使用一个创建完毕的对象来初始化一个对象。
stu p(10);
stu p1(p);
2.一值传递的方式给函数参数传值。
void f(stu p){
}
int main(){
stu p(10);
f(p);
}
函数f中的参数属于值传递,在拷贝的途中,运用到了拷贝构造函数
3.一值方式返回局部对象
stu f(){
stu p(10);
return p;
}
int main(){
stu f =f();
}
因为return是拷贝了一份p,所以运用到了拷贝构造函数
浅拷贝和深拷贝
浅拷贝是指默认拷贝构造函数对对象的成员进行简单的值拷贝
但是浅拷贝会在一些情况下出现问题,我们看一下代码
class P {
public :
int* point;
P(int a) {
this->point = new int(a);
}
};
int main() {
P p(10);
P p1(p);
cout <<*p.point<<endl;//10
cout << *p.point;//10
}
到这里一切都是正常的,因为在构造函数P中用new在堆中开辟了一片内存·,需要手动去释放。那么加一个析构函数去释放
~P() {
delete(point);
}
将这串代码放到类P中,发现报错了
这是问神魔呢?
浅拷贝会把指针变量的地址复制了,而对象p和p1都会调用析构函数(先调用p1然后p,函数先执行的后析构),
然而在第一次p1调用析构函数时,就已经将那块内存释放了,p再次调用时当然会报错了。
这时就要用深拷贝了
P(const P & p) {
this->point = new int(*p.point);
}
此时拷贝时会再开辟一款内存,所以析构时,将不会释放同一块内存了。
总结
浅拷贝:又称值拷贝,将源对象的值拷贝到目标对象中去,本质上来说源对象和目标对象共用一份实体,只是所引用的变量名不同,地址其实还是相同的。
深拷贝:拷贝的时候先开辟出和源对象大小一样的空间,然后将源对象里的内容拷贝到目标对象中去,这样两个指针就指向了不同的内存位置。并且里面的内容是一样的
上一篇: 构造和析构函数
下一篇: 机器猫还能变泳衣呢?