C++构造函数与析构函数

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、构造函数
    • 普通的析构函数
    • 拷贝构造函数
      • 深浅拷贝构造函数
    • 移动拷贝构造函数
  • 二、析构函数
    • 析构函数的构造
    • 构造与析构顺序问题
  • 总结:


前言

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、构造函数

普通的析构函数

  • 构造函数名字和类名相同
  • 构造函数没有返回值
  • 构造函数不需要自己调用,构造对象的过程就是调用构造函数的过程
    • 构造函数决定了对象的长相
    • 不写构造函数会存在一个默认的无参构造函数
      • default 去使用默认的构造函数
      • delete可以删掉默认的函数
例如:
	MM() = default;			//使用默认的构造函数
	MM() = delete;			//删掉默认的构造函数
  • 自己写了构造函数,默认的构造函数就不存在
  • 为了能够创建不同的对象
    • 函数重载
    • 函数缺省
  • 一般情况下构造函数是public属性,除了特殊需求可能是私有属性(设计模式–>单例)
  • 构造函数用来构造函数,说白一点就是初始化对象的数据
    注意:根据不同的参数调用不同的构造函数
#include 
#include 
using namespace std;
class MM 
{
public:
	MM(string xName, int xAge) 
	{
		name = xName;
		age = xAge;
		cout << "两个参数的对象" << endl;
	}
	MM() 
	{
		cout << "创建无参对象" << endl;
	}
protected:
	string name;
	int age;
};
//对象数组
class Data
{
public:
	Data() {}		//-->构造对象数组
	Data(string xName, int xAge)
	{
		name = xName;
		age = xAge;
	}
	void printData()
	{
		cout << name << "\t" << age << endl;
	}
	string& getName() { return name; }
	int& getAge() { return age; }
private:
	string name="默认";
	int age=101;
};
void testArray() 
{
	Data array[3];			//调用无参
	for (int i = 0; i < 3; i++) 
	{
		string name = "name";
		//to_string 把转换为字符串
		name += to_string(i);
		array[i].getName() = name;
		array[i].getAge() = i;
		array[i].printData();
	}
	//版本太低支持不了
	Data array2[3] = { {"name1",1}, {"name2",2}, {"name3",3} };
	for (int i = 0; i < 3; i++) 
	{
		array2[i].printData();
	}
}

int main() 
{
	MM  mmObject("十夏",138);
	MM mm;
	//new一个对象的过程
	//1.首先创建一个匿名对象
	//2.把匿名对象的首地址赋值给指针
	MM* pmm = new MM("狼",18);
	MM("匿名对象", 199);
	cout << "上面的对象已死亡" << endl;
	//构造和析构顺序
	//只要相关代码会创建一个新对象,就是调用构造函数
	MM  temp = { "调用构造函数",19 };
	
	int num = (int)1.11;   //C++中的强制类型转换
	int number = int(1.111);
	//复合数据{ "调用构造函数",19 }
	testArray();
	return 0;
}

拷贝构造函数

拷贝构造函数也叫做复制构造函数,拷贝构造函数也是构造函数,也是用来创建对象的 -----本质:通过一个对象去初始化另外一个对象

构造函数的参数是固定的:参数是对对象的引用

不写拷贝构造存在一个默认的拷贝

拷贝构造函数一般情况尽量用const修饰

#include 
#include 
#include 
using namespace std;
class MM
{
public:
	MM() {}
	MM(string xName, int xAge)
	{
		name = xName;
		age = xAge;
	}
	//拷贝构造函数
	MM(const MM& object)
	{
		name = object.name;
		age = object.age;
		cout << "调用拷贝构造函数" << endl;
	}
	void printMM() 
	{
		cout << name << "\t" << age << endl;
	}
private:
	string name;
	int age;
};
int main() 
{
	MM girl = { "十夏",138 };
	MM mm(girl);					//显示调用拷贝构造函数
	mm.printMM();
	girl.printMM();

	MM beautyGirl = mm;				//隐式调用拷贝构造函数
	beautyGirl.printMM();
	MM mm1;
	
	return 0;
}

深浅拷贝构造函数

深浅拷贝构造函数的区别:

1、浅拷贝: 默认的拷贝构造和不做内存申请的拷贝构造,只需释放一次内存
(因浅拷贝没有开辟新的内存,都是指向同一块内存)
      **默认的拷贝构造函数**
2、深拷贝: 在拷贝构造函数存在内存申请

两者之间的区别就是:有没有做内存申请

#include 
#include 
#include 
using namespace std;

class my_string
{
public:
	my_string(const char* xString)
	{
		size = strlen(xString);
		str = new char[size + 1];
		strcpy_s(str, size + 1, xString);
	}
	my_string(const my_string& object) 
	{
		//深拷贝: 拷贝构造函数做了内存申请
		size =object.size;
		str=new char[size+1];
		strcpy_s(str,size+1,object.str);
	}
	void deleteMemeory() 
	{
		delete[] str;
	}
	void printString() 
	{
		cout << str << endl;
	}
private:
	char* str;
	int size;
};
//No.2深浅拷贝
//包含指针并且做内存申请
void copyFunc() 
{
	//浅拷贝会导致内存是释放问题(重复释放)
	my_string str("ILoveyou");
	str.printString();
	my_string str1 = str;
	str1.printString();
	str1.deleteMemeory();
	str.deleteMemeory();
}
int main(){

	copyFunc();
	return 0;
}

移动拷贝构造函数

移动拷贝构造函数: 匿名对象拷贝构造

#include 
#include 
#include 
using namespace std;
class MM
{
public:
	MM() {}
	MM(string xName, int xAge)
	{
		name = xName;
		age = xAge;
	}
	MM(MM&& object) 
	{
		name = object.name;
		age = object.age;
		cout << "移动拷贝" << endl;
	}
	void printMM() 
	{
		cout << name << "\t" << age << endl;
	}
private:
	string name;
	int age;
};

二、析构函数

析构函数的构造

  • 析构函数的写法:~类名(参数){ }
  • 析构函数名: ~类名
  • 析构函数没有参数没有返回值
  • 析构函数在对象死亡的时候自动调用
  • 一般情况不需要写析构函数,当类的数据成员含有指针并且申请内存,需要大家手动写
class Test 
{
public:
	Test(string xInfo = "A")     //构造函数
	{
		info = xInfo;
		cout << info;
	}
	~Test()     				//析构函数
	{
		cout << info;
	}
private:
	string info;
};

构造与析构顺序问题

  • 一般情况构造顺序和析构顺序是相反
  • 静态对象最后释放
  • new出来对象,不做delete不会调用析构,调用delete 直接调用析构函数
    析构与构造顺序问题:1、所有函数的构造顺序 按构造的先后顺序 2、静态函数最后释放 3、new出来的对象什么时候调用delet,什么时候调用析构函数,不调用delete不析构 4一般情况下,析构顺序与构造顺序相反
#include 
#include 
using namespace std;
class Test 
{
public:
	Test(string xInfo = "A") 
	{
		info = xInfo;
		cout << info;
	}
	~Test() 
	{
		cout << info;
	}
private:
	string info;
};
int main()
{
	{
		static Test st("C");			//C
		Test t1;						//A
		Test* p = new Test("B");		//B
		delete p;						//B
		Test t2[3]{ {"0"},{"1"},{"2"}};						//AAA
		//CABBAAA AAAAC
	}
	cout << "一般情况" << endl;
	{
		Test t1("1");
		Test t2("2");
		Test t3("3");
		//123321
	}
	cout << "静态对象" << endl;
	{
		Test t1("1");
		Test t2("2");
		Test t3("3");
		static Test st("s");
		//123321
	}
	cout << endl << "new出来的对象" << endl;
	{
		Test t1("1");				//1
		Test t2("2");				//2
		Test* p = new Test("n");	//n
		delete p;					//n
		Test t3("3");				//3
	}
	return 0;
}

总结:

讲述了常用有参、无参的构造函数,拷贝构造与深浅拷贝以及类的构造顺序与析构顺序。

你可能感兴趣的:(C++,c++)