C++学习笔记(十):构造函数和析构函数

本文详细介绍了构造函数和析构函数的作用,包括它们的语法、调用时机以及默认实现。同时,阐述了有参构造、无参构造和拷贝构造的区别,并解释了为何拷贝构造函数需要使用引用。还讨论了深拷贝和浅拷贝的概念,以及在内存管理中避免浅拷贝可能导致的问题。最后,提到了析构函数的使用和作用。
摘要由CSDN通过智能技术生成

构造函数和析构函数

构造函数:给对象进行初始化,主要为对象的成员属性。
析构函数:清理对象。

必须有构造函数和析构函数,一般控制权限都是public。如果用户不提供,则使用编译器提供的构造函数和析构函数,编译器提供的构造函数和析构函数是空实现(对成员属性什么都不做)。
构造函数和析构函数编译器自动调用
先创建构造函数的实例后调用析构函数

构造函数:

语法:类名( ) { }

  1. 没有返回值,也不需要写void
  2. 函数名称和类名相同
  3. 构造函数可以有参数,也可以重载
  4. 调用对象时自动调用,且只调用一次。
    //析构函数
    Person(string _name){
       name=_name;
   }
   Person(string _name,int _age){
       name=_name;
       age=_age;
   }

分类
按参数分:有参构造和无参(默认)构造

Person(){
	cout<<"无参构造"<<endl;
}
Person(string name){
	cout<<"有参构造"<<endl;
}

按类型分:普通构造和拷贝(copy)构造
拷贝构造函数中必须使用引用
原因:如果通过值传递的方式,调用拷贝函数时就要进行实例化一个对象,实例化对象又要调用拷贝函数,形成无限递归。

Person(const Person& p){
	name = p.name;
	age = p.age;
}

拷贝构造函数的作用:

  1. 使用一个创建完成的对象来初始化另一个对象
  2. 值传递时给函数传参
  3. 函数返回一个对象

默认情况

  1. 默认构造函数,无参,函数体为空

  2. 默认析构函数,无参,函数体为空

  3. 默认拷贝构造函数,对属性进行值拷贝

    注意事项:

    1. 如果用户定义有参构造函数,则编译器不再提供上述1的默认构造函数
    2. 如果用户定义拷贝构造函数,则编译器不再提供上述1和3提供的构造函数

深拷贝和浅拷贝
浅拷贝:值拷贝,编译器提供的默认拷贝函数就是浅拷贝

class Person {
public:
	string name;
	int* age;
	
	Person(string _name, int _age) {
		name = _name;
		age = new int(_age);
	}

	~Person() {
		if (age != NULL) {
			delete age;
			age = NULL;
		}
		cout << "析构函数启动" << endl;
	}
};
.
.
.
Person p1("killer", 23);
cout << *(p1.age) << endl;
Person p2(p1);
cout << *(p2.age) << endl;//报错
return 0;

在这里插入图片描述

深拷贝:在堆区重新申请空间,进行拷贝操作

class Person {
public:
	string name;
	int* age;
	
	Person(string _name, int _age) {
		name = _name;
		age = new int(_age);
	}

    //用户定义的深拷贝函数
	Person(const Person& p) {
		name = p.name;
		age = new int(*(p.age));
	}
	~Person() {
		if (age != NULL) {
			delete age;
			age = NULL;
		}
		cout << "析构函数启动" << endl;
	}
};

在这里插入图片描述
调用

  1. 括号法
Person p0;//无参构造
Person p1 ("张三");//有参构造
Person p2 (p1);//拷贝构造
   注意事项:
   1. 调用无参构造时Person p0 ( );//错误,编译器会认为这是一个函数声明
  1. 显示法
Person p1 = Person("张三");//有参构造
Person p2 = Person(p1);//拷贝构造
 注意事项:
 1. Person("张三")是一个匿名对象,在当前行执行完后,编译器就会释放该匿名对象。
 2. 不要利用拷贝构造函数初始化一个匿名对象
     Person  (p3);//错误,Person (p3);相当于Person p3;

3.隐式转换法

string str = "张三";
Person p1 = str;//相当于Person p1 = Person("张三");
Person p2 = p1;//相当于Person p2 = Person(p1);
析构函数

语法:~类名( ) { }

  1. 没有返回值,也不需要void
  2. 函数名称与类名相同,在名称前加符号~
  3. 析构函数没有参数,不能重载
  4. 在对象销毁前自动调用,且只调用一次。
    ~Person(){
        cout<<"end"<<endl;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值