广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++超详细讲解构造函数与析构函数的用法及实现
  • 354
分享到

C++超详细讲解构造函数与析构函数的用法及实现

2024-04-02 19:04:59 354人浏览 泡泡鱼
摘要

目录写在前面构造函数和析构函数语法作用代码实现两大分类方式三种调用方式括号法显示法隐式转换法正确调用拷贝构造函数正常调用值传递的方式给函数参数传值值传递方式返回局部对象构造函数的调用

写在前面

上一节解决了类与对象封装的问题,这一节就是对象的初始化和清理的构造函数与析构函数的内容了;对象的初始化和清理也是两个非常重要的安全问题:一个对象或者变量没有初始状态,对其使用后果是未知,同样的使用完一个对象或变量,没有及时清理,也会造成一定的安全问题;c++利用了构造函数和析构函数解决上述问题,这两个函数将会被编译器自动调用,完成对象初始化和清理工作。对象的初始化和清理工作是编译器强制要我们做的事情,因此如果我们不提供构造和析构,编译器提供编译器提供的构造函数和析构函数是空实现。下面开始正文:

构造函数和析构函数

语法

构造函数语法: 类名(){}

1、没有返回值也不写void

2、函数名称与类名相同

3、构造函数可以有参数,因此可以发生重载

4、程序在调用对象时会自动调用,无需手动调用且只会调用一次

析造函数语法: ~类名(){}

1、没有返回值也不写void

2、函数名称与类名相同,在名称前加上符号~

3、构造函数不可以有参数,因此不可以发生重载

4、程序在对象销毁前会自动调用析构,无需手动调用且只会调用一次

作用

构造函数 主要作用于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用

析构函数 主要作用于对象销毁前系统自动调用,执行一些清理工作

代码实现

#include<iOStream>
using namespace std;
class Person
{
public:
	Person()
	{
		cout << "Person构造函数的调用" << endl;
	}
	~Person()
	{
		cout << "~Person析构函数的调用" << endl;
	}
};
void test01()
{
	Person p;//栈上的对象运行完毕后,编译器自动释放
}
int main()
{
	test01();
}

test01中创建了Person类p,主函数只是调用了一下创建的Person类p,编译器就自动调用了类的构造函数和析构函数,析构函数是程序运行完毕后,编译器自动清理内存空间的时候调用的。

两大分类方式

按参数分为 有参构造 和 无参构造

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

无参和有参构造很好理解,就是有无参数的区别,这里讲一下拷贝构造函数:

//拷贝构造函数
	Person(const Person &p) //格式: const 类名 引用(&)变量名
	{
		//讲传入的人身上的所有属性,拷贝到我身上
		age = p.age;
		cout << "Person的拷贝构造函数调用" << endl;
	}

Person()的括号中是const Person &p,这是拷贝构造的函数格式,他需要传入相同类的对象,会产生一个具有相同属性的类,比如p1的年龄为20,经过拷贝构造p2的年龄也会是20,但是两个类对象的地址并不相同,这个到后面会具体解释

三种调用方式

class Person
{
public:
	//构造函数
	Person()
	{
		cout << "Person的无参构造函数调用" << endl;
	}
	Person(int a)
	{
		age = a;
		cout << "Person的有参构造函数调用" << endl;
	}
	//拷贝构造函数
	Person(const Person &p) //格式: const 类名 引用(&)变量名
	{
		//讲传入的人身上的所有属性,拷贝到我身上
		age = p.age;
		cout << "Person的拷贝构造函数调用" << endl;
	}
	~Person()
	{
		cout << "~Person的析构函数调用" << endl;
	}
	int age;
};

括号法

    Person p;//默认构造函数调用
	Person p2(10);//有参构造函数
	Person p3(p2);//拷贝构造函数
	cout << "p2 age=" << p2.age << endl;
	cout << "p3 age=" << p3.age << endl;

注意事项:调用默认构造函数的时候,不要加();Person p1() 编译器会认为是函数的声明,不认为在创建对象,等同于 void func()

显示法

    Person p;
	Person p2=Person(10);//有参构造函数
	Person p3=Person(p2);//拷贝构造函数
	Person(100);//匿名对象,特点:当前执行完毕后,系统会立即回收掉匿名对象
	cout << "AAAAA" << endl;

注意事项2:拷贝构造初始化匿名对象等同于去掉括号,导致重定义,不要用拷贝构造初始化匿名对象,如果利用匿名对象的话,会和Peron p2=Person(10),重复,出现重定义错误;也不要用拷贝构造初始化匿名对象。

隐式转换法

    Person p2 = 10;// 有参构造函数
	Person p3 = p2;// 拷贝构造函数

这个方法不推荐使用,调用的很不明显,建议使用前面两个方法调用构造函数。

正确调用拷贝构造函数

class Person
{
public:
	Person()
	{
		cout << "Person的无参构造函数调用" << endl;
	}
	Person(int a)
	{
		m_age = a;
		cout << "Person的有参构造函数调用" << endl;
	}
	Person(const Person& p)
	{
		m_age = p.m_age;
		cout << "Person的拷贝构造函数调用" << endl;
	}
	~Person()
	{
		cout << "Person 的析构函数调用" << endl;
	}
	int m_age;
};

正常调用

void test01()
{
	Person p1(20);
	Person p2(p1);
	cout << "p2的年龄为:" << p2.m_age << endl;
}

主函数中直接调用test01,这时候会显示 p2的年龄为20,并且打印:拷贝构造函数的调用。所以说,使用一个已经创建完毕的对象来初始化一个新对象的时候会调用拷贝构造函数

值传递的方式给函数参数传值

void doWork(Person p)
{  }
void test02()
{
	Person p;
	doWork(p);
}

大家可以猜一下,在主函数调用,会运行出什么结果,答案是:无参构造函数调用和拷贝构造函数调用,最后是两个析构函数调用;浅析一下过程,调用test02时创建了对象P,所以自动调用无参构造函数,当运行到doWork(p)时,调用拷贝构造函数,随后拷贝构造函数被清理,调用析构函数,程序结束前,p被清理,再次调用析构函数,程序结束。

值传递方式返回局部对象

Person doWork2()
{
	Person p1;
	cout << (int)&p1<<"  1  " << endl;
	return p1;//返回就拷贝构造函数,随后释放掉,调用析构
}
void test03()
{
	Person p = doWork2();//重新创建局部对象,并不是上面返回的对象p1
	cout << (int)&p<<"  2  " << endl;
}

这里doWork2返回值时Person类型,也就是说return p1后会拷贝构造其属性给test03调用的p,但是p1和p2并不是同一个对象,我们可以输出他们的地址来验证。

这里的调用顺序是:Person P1 的无参构造,随后输出p1地址,然后返回值的时候先调用拷贝构造函数,把值赋给p,随后清理p1调用析构;然后回到test03中,输出p的地址,程序结束前调用析构,程序结束。

构造函数的调用规则

编译器提供:

1、创建一个类,c++编译器会给每个类都至少添加三个函数

  1. 默认构造(空实现)
  2. 析构函数(空实现)
  3. 值拷贝构造(值拷贝)

2、如果我们写了有参构造,编译器不再提供默认构造,但是提供值拷贝构造

如果我们写了拷贝构造函数,编译器不再提供其他普通构造函数

void test01()
{
	Person p1;
	p1.m_age = 19;
	Person p2(p1);//即使没写拷贝构造仍然能得到结果p2.m_age =19
	cout << "p2的年龄为:" << p2.m_age << endl;
}

也就是说,就算我们不写无参和拷贝构造,调用test03也会得到值拷贝后的p2年龄,这是编译器默认提供的三个函数。但是如果写了有参构造,Person p1这行代码就会报错,提示找不到默认构造函数;同样的如果自己写了拷贝构造,Person p1也会显示同样的错误。

总结

这篇博文讲了一部分对象的初始化和清理的内容,着重讲了构造函数的调用方法、规则,以及拷贝构造函数的概念,调用方法和细节。下一篇直接准备深浅拷贝的内容和初始化列表,静态成员等的问题,彻底结束对象的初始化和清理内容,期待下篇与你们见面!

到此这篇关于C++超详细讲解构造函数与析构函数的用法及实现的文章就介绍到这了,更多相关C++构造函数与析构函数内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++超详细讲解构造函数与析构函数的用法及实现

本文链接: https://www.lsjlt.com/news/149921.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++超详细讲解构造函数与析构函数的用法及实现
    目录写在前面构造函数和析构函数语法作用代码实现两大分类方式三种调用方式括号法显示法隐式转换法正确调用拷贝构造函数正常调用值传递的方式给函数参数传值值传递方式返回局部对象构造函数的调用...
    99+
    2022-11-13
  • C++超详细讲解构造函数
    目录类的6个默认成员函数构造函数特性编译器生成的默认构造函数成员变量的命名风格类的6个默认成员函数 如果我们写了一个类,这个类我们只写了成员变量没有定义成员函数,那么这个类中就没有函...
    99+
    2022-11-13
  • C++超详细讲解析构函数
    目录特性析构函数处理自定义类型编译器生成的默认析构函数特性 析构函数是特殊的成员函数 特征如下: 析构函数名是~类名;无参数无返回值;一个类有且只有一个析构函数;对象声明周期结束,编...
    99+
    2022-11-13
  • C++超详细讲解拷贝构造函数
    目录构造函数特征编译器生成的拷贝构造拷贝构造的初始化列表显式定义拷贝构造的误区结论构造函数 只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对...
    99+
    2022-11-13
  • Python构造函数与析构函数超详细分析
    目录1.构造函数2.析构函数1.构造函数 __init__(self), 这个方法就是构造函数,在实例化的时候自动调用。 所有如果这个函数内有打印的方法,当实例出来的时候会打印里面的...
    99+
    2022-11-13
    Python构造函数与析构函数 Python析构函数 Python构造函数
  • Golang创建构造函数的方法超详细讲解
    目录组合字面量自定义构造函数从构造函数返回错误interface构造函数最佳实践基本构造函数主包类型多个构造函数组合字面量 组合字面量是最直接方式初始化Go对象,假设定义了Book类...
    99+
    2023-01-28
    Go创建构造函数 Go构造函数
  • C++类与对象及构造函数析构函数基础详解
    目录C++类与对象类的定义对象的创建构造函数和析构函数访问修饰符继承多态成员变量与成员方法总结C++类与对象 C++是一门面向对象的编程语言。在C++中,我们可以利用类来创建对象,...
    99+
    2023-05-16
    C++类对象函数 c++ 构造析构函数
  • C++中构造函数与析构函数的详解及其作用介绍
    目录构造函数默认构造函数有参构造函数析构函数析构函数例子析构函数执行时机局部对象全局对象构造函数 构造函数 (constructor) 是一种特殊的成员函数. 它会在每次创建类的新对...
    99+
    2022-11-12
  • c++详细讲解构造函数的拷贝流程
    #include <iostream> #include <string> using namespace std; void func(string str...
    99+
    2022-11-13
  • C++类与对象深入之构造函数与析构函数详解
    目录对象的初始化和清理一:构造函数1.1:构造函数的特性1.2:构造函数的分类二:析构函数2.1:概念2.2:特性三:拷贝构造函数3.1:概念3.2:特性3.3:拷贝构造函数调用时机...
    99+
    2022-11-13
  • C++实现拷贝构造函数的方法详解
    目录引入一.什么是拷贝构造函数二.什么情况下使用拷贝构造函数三.使用拷贝构造函数需要注意什么四.深拷贝浅拷贝4.1 浅拷贝4.2 深拷贝引入 对于普通类型的对象来说,他们之间的复制很...
    99+
    2022-11-13
  • C++编程析构函数拷贝构造函数使用示例详解
    目录构造函数析构函数拷贝构造之深拷贝和浅拷贝深浅拷贝区别首先定义一个类进行操作。 class MM { public: protected: int year; ...
    99+
    2022-11-12
  • C++构造析构赋值运算函数应用详解
    目录了解C++默默编写哪些函数不想使用编译器函数为多态基类声明virtual析构函数别让异常逃离析构函数绝不在构造和析构过程中调用virtual函数令operator=返回一个ref...
    99+
    2022-11-13
  • Kotlin类与属性及构造函数的使用详解
    目录1.类的属性 filed2.构造函数3.执行顺序4.延迟初始化5.惰性初始化1.类的属性 filed 1)在kotlin中定义属性,必须赋初始值,要不编译器检查不通过。这个和ja...
    99+
    2022-11-13
  • C++构造函数初始化列表的实现详解
    目录1.前言2.初始化列表3.注意事项1.前言 初始化就是给变量一个初始值。 初始化的目的是为了让变量有值,防止使用时出现异常。 在构造函数中,有一项重要功能就是对成员变量进行初始化...
    99+
    2022-11-13
  • C语言超详细讲解getchar函数的使用
    目录一、getchar 函数二、缓冲区1、什么是缓冲区2、为什么要存在缓冲区3、缓冲区的类型4、缓冲区的刷新三、getchar 函数的正确使用1、getchar 的换行问题2、get...
    99+
    2022-11-13
  • C#继承与构造函数的调用实例
    本篇内容介绍了“C#继承与构造函数的调用实例”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!C#继承构造函数的调用实例演示using ...
    99+
    2023-06-18
  • C语言超详细讲解函数指针的运用
    目录前言计算器的例子回调函数转移表前言 前面我们学习了各种各样的指针类型,有些指针可以说是稀奇百怪,特别是函数指针,有些朋友可能觉得,函数指针有些多余,调用函数为什么要用指针调用,直...
    99+
    2022-11-13
  • C++详细讲解常用math函数的用法
    目录1、fabs(double x)2、floor(double x)ceil(double x)3、pow(double x,double n)4、sqrt(double x)5、...
    99+
    2022-11-13
  • C++右值引用与移动构造函数基础与应用详解
    目录1.右值引用1.1左值右值的纯右值将亡值右值1.2右值引用和左值引用2.移动构造函数2.1完美的移动转发1.右值引用 右值引用是 C++11 引入的与 Lambda 表达式齐名的...
    99+
    2023-02-13
    C++右值引用 C++移动构造函数
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作