C++的构造与析构函数

构造函数

  • 构造函数长什么样子
    - 函数名与类名相同
    - 没有返回值
    void也是有返回值值的
    - 如果不写构造函数,任何类中都存在一个默认的构造函数
    默认的构造函数是无参的
    当我们写了构造函数,默认的函数就被删掉了
    - 构造函数在构造对象的时候,默认调用
    - delete可以用来删掉默认的构造函数
    类名()=delete;
    -指定使用默认的无参构造函数,用default说明
    类名() = default;
    - 允许构造函数调用另一个构造函数,只是要用初始化参数列表的方式
    - 初始化参数列表:只有构造函数有
    构造函数名(参数1,参数2...):成员1(参数1),成员2(参数2)...{} (避免形参命和数据成员命相同导致的问题)
  • 构造函数是用来干嘛的
    -用来构造对象的
    - 构造函数更多是用来树池话数据成员的
  • 构造函数的几个思考题
    -为什么不写构造函数可以构造对象?(因为存在一个默认的无参构造函数,所以再不写的时候,只可以构造无参的对象)
    - 构造函数为什么要重载?(为了构造不同长相的对象)
//初始化参数列表
class Tihu1{
	public:
		Tihu1(string nname = "Tihu",int nage = 19):name(nname),age(nage){}
		void print(){
			cout<<name<<"\t"<<age<<endl;
		}
	protected:
			string name ;
			int age ;
};
//构造函数的缺省 
class Tihu2{
	public:
		Tihu2(string nname = "Tihu二",int nage = 19){
			name = nname;
			age = nage;	
			}	
		void print(){
			cout<<name<<"\t"<<age<<endl;
		}
	protected:
			string name ;
			int age ;
};
int main(void){
	Tihu1 A1("Tihu1",20);
	Tihu1 A2("Tihu2",21);
	Tihu2 A3;
	A1.print();
	A2.print();
	A3.print();	
	return 0;
}

析构函数

  • 析构函数长什么样子
    • 无返回值
    • 无参数
    • 函数名:类名
    • 不写的话存在默认的析构函数
    • 析构函数不需要自己调用,在对象的生命周期结束的时候执行
  • 析构函数是用来干嘛的
    -当类中数据成员是指针的时候,用动态内存申请写构造函数以及析构函数
    - 释放数据成员申请的动态内存
class Tihu2{
	public:
		Tihu2(const char *nname ="Tihu",int nage = 19){
			name = new char[strlen(nname)+1];
			strcpy(name,nname);
			cout<<strlen(nname)+1<<endl;
			age = nage;	
			}	
		void print(){
			cout<<name<<"\t"<<age<<endl;
		}
		//析构函数
		~Tihu2(){
			cout<<"我是析构函数"<<endl; 
			delete [] name;
		}
	protected:
			char* name ;
			int age ;
};

拷贝构造函数

  • 拷贝构造函数也是一个构造函数,长相与构造函数相同,也是用来构造对象的,只是
    参数是唯一的,是对对象的引用
    Tihu(const Tihu& A1 )
  • 不写的话也是存在默认的拷贝构造该函数,不过这个默认的是浅拷贝,在元素含有指针的时候不适用。
  • 拷贝构造函数的作用:用一个对象去初始化另一个对象
  • 当存在匿名对象赋值操作的时候,必须加const
class Tihu
{
	public:
	//拷贝构造的定义方法
	Tihu(const Tihu& A1)
	{
		age = A1.age;
	}
	protected:
	int age;
}

深拷贝与浅拷贝

  • 浅拷贝:默认的拷贝构造为浅拷贝
  • 深拷贝:拷贝构造中做了new的内存操作,因为浅拷贝再有指针的情况下,只是给指针确定的指向,并不是给指针申请新的空间,导致在析构函数里,内存释放会出错
class Tihu
{
	public:
	Tihu(char nname[] = "Tihu",int nage = 19):age(nage)
	{
		name = new char[strlen(nname)+1];
		strcpy(name,nname);
	}
	Tihu(const Tihu& A1)
	{
		name = new char[sizeof(*A1.name)];
		strcpy(name,A1.name);
	}
	~Tihu()
	{
		delete[] name;
	}
	protected:
		char* name;
		int age;
}

Tihu A1("Tihu1",10);
Tihu A2(A1);
printf("A1.name:%p\n",A1.name);
printf("A2.name:%p\n",A2.name);

构造与析构顺序

  • 普通对象,构造顺序和析构顺序是相反的
  • new出来的对象,delete会直接调用析构函数
  • static对象,当程序关闭的时候,生命周期才会结束
#include <iostream>
#include <string>
using namespace std;
class MM 
{
public:
	MM(string name="x") :name(name) {
		cout << name;
	}
	~MM(){
		cout << name;
	}
protected:
	string name;
};
int main() 
{
	{
		MM mm1("A");			//A
		static MM mm2("B");		//B   程序关闭时候才死亡,最后析构
		MM* p3 = new MM("C");	//C
		MM mm4[4];				//xxxx
		delete p3;				//C  delete 直接调用析构
		p3 = nullptr;
								//xxxxAB
	}
	//ABCxxxxCxxxxAB
	return 0;
}

C++结构体

  • 在c++的结构体中,如果加了构造函数,那么必须使用c++类的方式是使用这个结构体,唯一的区别就是结构体中的默认区域为公共属性,而类中的默认区域为私有属性。

作业

  • mystring类的实现
    1. 实现string中创建方式
    2. 通过实现data和c_str函数 打印字符串
    3. 实现append 实现字符串的链接
    4. 实现字符串比较
    5. 手写析构函数释放内存
 #include <iostream>
 #include <cstring> 
 using namespace std;
 /* 
 mystring类的实现
 	1. 实现string中创建方式
 	2. 通过实现data和c_str函数 打印字符串
 	3. 实现append 实现字符串的链接
 	4. 实现字符串比较
 	5. 手写析构函数释放内存
*/
class mystring
{
	public:
		mystring(char str1[]="默认值"){
			str = new char[strlen(str1)+1];
			strcpy(str,str1);
		}
		mystring(const mystring& object){
			str = new char[strlen(object.str)+1];
			strcpy(str,object.str);
		}
		//5.手写析构函数释放内存
		~mystring(){
			delete[] str;
		}
		char* data(){
			return str;
		} 
		char* c_str(){
			return str;
		}
		void print(){
			cout<<str<<endl;
		}
		mystring append(const mystring& object){
			int n=strlen(str);
			int sum = n+strlen(object.str)+1;
			char* ptemp = new char[sum];
			int i=0;
			while(1){
				if(i<strlen(str)){
					ptemp[i] = str[i];
				}
				else if(i>=strlen(str)&&i<sum-1){
					ptemp[i] = object.str[i-n];
				}
				else{
					ptemp[i] = 0;
					break;
				}		
			}
			mystring A1(ptemp);
			delete[] ptemp;
			ptemp = NULL;
			return A1;
		}
		int compare(const mystring& object){
			return strcmp(str,object.str);
		} 
	protected:
		char* str;		
}; 
int main(){
	//	1. 实现string中创建方式
	mystring str1;
	mystring str2("ILoveyou");
	mystring str3(str1);
	str3.print();
	mystring str4 = str2;
	str4.print();
	//2. 通过实现data和c_str函数 打印字符串
	cout << str2.c_str() << endl;  //打印ILoveyou
	cout << str2.data() << endl;   //打印ILoveyou
	//3.实现append 实现字符串的链接
	string strOne="one";
	string strTwo="two";
	string strThree=strOne.append(strTwo);
	cout<<strThree.data()<<endl;	    //onetwo
	//4.实现字符串比较
	cout<<strOne.compare(strOne)<<endl;	//0
	cout<<strOne.compare(strTwo)<<endl;	//-1
	cout<<strTwo.compare(strOne)<<endl;	//1
	//5.手写析构函数释放内存
	
	return 0;
}
  • 运行结果
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值