ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C++ 对象的初始化与清理——详解构造、析构、拷贝函数的功能

2020-03-06 13:39:51  阅读:232  来源: 互联网

标签:初始化 函数 C++ Person 构造 析构 拷贝 构造函数


对象的初始化与清理

  • 对于一个对象而言,如何设置最初的初始化参数与清理对象的数据呢?由次引入了两种函数——构造函数与析构函数。

1.1构造函数与析构函数

  • 构造与析构函数本身是由编译器自动调用的,创建对象时调用构造函数,函数返回时在通过析构函数将对象内的数据进行一个销毁。如果不进行定义函数,编译器会自动调用空函数。
  • 构造函数名称为类名称,析构函数名称为~类名称
//1、构造函数与析构函数
//析构函数在栈释放后执行
//构造与析构函数都是只执行一次,构造用于初始化,析构用于清除数据
class Person
{
public:
	//构造函数
	Person()
	{
		cout << "Person的构造函数调用" << endl;
	}
	//析构函数
	~Person()
	{
		cout << "Person的析构函数调用" << endl;
	}

};

void test01()
{
	Person p;
}

int main() {
	
	test01();

	system("pause");

	return 0;
}

1.2构造函数的分类与调用

  • 构造函数分为有参数、无参数、拷贝函数三类。函数定义过程中无需写函数类型,也不用写return返回值
  • 拷贝函数的意义在于将别的对象的参数进行拷贝,如下例子中person(const person &p)
  • 调用方法分为括号法、显示、隐示三类方法。
//2、构造函数的分类与调用
#include <iostream>

using namespace std;

//1、构造函数分类

// 按照参数分类分为 有参和无参构造   无参又称为默认构造函数

// 按照类型分类分为 普通构造和拷贝构造



class Person {

public:

        //无参(默认)构造函数

        Person() {

               cout << "无参构造函数!" << endl;

        }

        //有参构造函数

        Person(int a) {

               age = a;

               cout << "有参构造函数!" << endl;

        }

        //拷贝构造函数

        Person(const Person& p) {

               age = p.age;

               cout << "拷贝构造函数!" << endl;

        }

        //析构函数

        ~Person() {

               cout << "析构函数!" << endl;

        }

public:

        int age;

};

//调用有参的构造函数

        void test02() {



               //2.1  括号法,常用

               Person p0;

               Person p1(10);

               //注意1:调用无参构造函数不能加括号,如果加了编译器认为这是一个函数声明

               //Person p2();

               Person p2(p1);



               //2.2 显式法

               Person p3 = Person(10);

               Person p4 = Person(p3);

               //Person(10)单独写就是匿名对象  当前行结束之后,马上析构



               //2.3 隐式转换法

               Person p5 = 10; // Person p4 = Person(10); 

               Person p6 = p5; // Person p5 = Person(p4); 



}

int main()

{

        test02();

        system("pause");

        return 0;

}

1.3拷贝函数的调用

//3、拷贝函数调用的三种方式
class Person {
public:
	Person() {
		cout << "无参构造函数!" << endl;
		mAge = 0;
	}
	Person(int age) {
		cout << "有参构造函数!" << endl;
		mAge = age;
	}
	Person(const Person& p) {
		cout << "拷贝构造函数!" << endl;
		mAge = p.mAge;
	}
	//析构函数在释放内存之前调用
	~Person() {
		cout << "析构函数!" << endl;
	}
public:
	int mAge;
};

//1. 使用一个已经创建完毕的对象来初始化一个新对象
void test01() {

	Person man(100); //p对象已经创建完毕
	Person newman(man); //调用拷贝构造函数
	Person newman2 = man; //拷贝构造

	//Person newman3;
	//newman3 = man; //不是调用拷贝构造函数,赋值操作
}

//2. 值传递的方式给函数参数传值
//相当于Person p1 = p;
void doWork(Person p1) {}
void test02() {
	Person p; //无参构造函数
	doWork(p);
}

//3. 以值方式返回局部对象
Person doWork2()
{
	Person p1;
	cout << (int *)&p1 << endl;
	return p1;
}

void test03()
{
	Person p = doWork2();
	cout << (int *)&p << endl;
}


int main() {

	//test01();
	//test02();
	test03();

	system("pause");

	return 0;
}

1.4无参构造、有参构造、拷贝构造之间的调用规则

  • 当自定义了有参构造的时候,无法调用其默认的无参构造,但仍可以调用编译器默认的拷贝构造。
  • 当自定义了拷贝构造,其他的默认构造全部失效。

class Person {
public:
	//无参(默认)构造函数
	Person() {
		cout << "无参构造函数!" << endl;
	}
	//有参构造函数
	Person(int a) {
		age = a;
		cout << "有参构造函数!" << endl;
	}
	//拷贝构造函数
	Person(const Person& p) {
		age = p.age;
		cout << "拷贝构造函数!" << endl;
	}
	//析构函数
	~Person() {
		cout << "析构函数!" << endl;
	}
public:
	int age;
};

void test01()
{
	Person p1(18);
	//如果不写拷贝构造,编译器会自动添加拷贝构造,并且做浅拷贝操作
	Person p2(p1);

	cout << "p2的年龄为: " << p2.age << endl;
}

void test02()
{
	//如果用户提供有参构造,编译器不会提供默认构造,会提供拷贝构造
	Person p1; //此时如果用户自己没有提供默认构造,会出错
	Person p2(10); //用户提供的有参
	Person p3(p2); //此时如果用户没有提供拷贝构造,编译器会提供

	//如果用户提供拷贝构造,编译器不会提供其他构造函数
	Person p4; //此时如果用户自己没有提供默认构造,会出错
	Person p5(10); //此时如果用户自己没有提供有参,会出错
	Person p6(p5); //用户自己提供拷贝构造
}

int main() {

	test01();

	system("pause");

	return 0;
}

1.5浅拷贝与深拷贝

  • 浅拷贝是指拷贝函数进行的是把原函数中的值进行拷贝,而深拷贝,是能够申请堆空间。
  • 利用浅拷贝删除的时候会出现重复清理一个堆空间而报错的情况
//17、析构函数用来释放堆栈函数,若利用浅拷贝的话,会导致堆栈被两次释放,即重复释放,这时需要利用深拷贝来进行解决,深拷贝相比于浅拷贝的值传递,会在堆栈中重新申请空间。
class Person {
public:
	//无参(默认)构造函数
	Person() {
		cout << "无参构造函数!" << endl;
	}
	//有参构造函数
	Person(int age ,int height) {
		
		cout << "有参构造函数!" << endl;

		m_age = age;
		m_height = new int(height);
		
	}
	//拷贝构造函数  
	Person(const Person& p) {
		cout << "拷贝构造函数!" << endl;
		//如果不利用深拷贝在堆区创建新内存,会导致浅拷贝带来的重复释放堆区问题
		m_age = p.m_age;
		m_height = new int(*p.m_height);
		
	}

	//析构函数
	~Person() {
		cout << "析构函数!" << endl;
		if (m_height != NULL)
		{
			delete m_height;
		}
	}
public:
	int m_age;
	int* m_height;
};

void test01()
{
	Person p1(18, 180);

	Person p2(p1);

	cout << "p1的年龄: " << p1.m_age << " 身高: " << *p1.m_height << endl;

	cout << "p2的年龄: " << p2.m_age << " 身高: " << *p2.m_height << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

1.6初始化列表操作


class Person {
public:

	////传统方式初始化
	//Person(int a, int b, int c) {
	//	m_A = a;
	//	m_B = b;
	//	m_C = c;
	//}

	//初始化列表方式初始化
	Person(int a, int b, int c) :m_A(a), m_B(b), m_C(c) {}
	void PrintPerson() {
		cout << "mA:" << m_A << endl;
		cout << "mB:" << m_B << endl;
		cout << "mC:" << m_C << endl;
	}
private:
	int m_A;
	int m_B;
	int m_C;
};

int main() {

	Person p(1, 2, 3);
	p.PrintPerson();


	system("pause");

	return 0;
}

1.7类中含类的构造析构顺序

在构造过程中,被包含的类先被构造,析构过程中,被包含的类后被析构


class Phone
{
public:
	Phone(string name)
	{
		m_PhoneName = name;
		cout << "Phone构造" << endl;
	}

	~Phone()
	{
		cout << "Phone析构" << endl;
	}

	string m_PhoneName;

};


class Person
{
public:

	//初始化列表可以告诉编译器调用哪一个构造函数
	Person(string name, string pName) :m_Name(name), m_Phone(pName)
	{
		cout << "Person构造" << endl;
	}

	~Person()
	{
		cout << "Person析构" << endl;
	}

	void playGame()
	{
		cout << m_Name << " 使用" << m_Phone.m_PhoneName << " 牌手机! " << endl;
	}

	string m_Name;
	Phone m_Phone;

};
void test01()
{
	//当类中成员是其他类对象时,我们称该成员为 对象成员
	//构造的顺序是 :先调用对象成员的构造,再调用本类构造
	//析构顺序与构造相反
	Person p("张三" , "苹果X");
	p.playGame();

}
int main() {

	test01();

	system("pause");

	return 0;
}

标签:初始化,函数,C++,Person,构造,析构,拷贝,构造函数
来源: https://blog.csdn.net/w794746725/article/details/104693568

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有