【C++入门】(拷贝)构造函数和析构函数

2023-10-31

1、构造函数和析构函数

(1)构造函数(constructor):字面意思就是构造对象的函数,当我们定义类的对象时调用,可以帮我们完成对象的初始化;
(2)析构函数(destructor):可以看做是构造函数的逆过程,当销毁类的时候调用,做一些收尾的工作;比如:定义类的对象时构造函数申请了动态内存,那在销毁对象时调研员的析构函数中就要释放申请的动态内存,否则就会造成内存泄漏;
(3)构造/析构函数是C++语言自带的回调函数。程序员可以在定义类时使用默认的构造/析构函数,或者自己定义构造/析构函数,但是构造/析构函数的调用却不是程序员主动去调用,而是C++语言自动帮我们调用。比如:定义类的对象时就会自动调用构造函数,销毁类的时候就会调用析构函数,程序员只需要定义类或者销毁类,构造/析构函数的调用是自动的;

2、构造函数和析构函数的使用

(1)C++在定义类时会提供默认的构造/析构函数,默认的构造/析构函数可以看做是空函数,什么也没做,如果我们没有需求可以在类中不定义构造/析构函数;
(2)如果我们在类中定义了构造/析构函数,则C++提供的默认构造/析构函数就失效了,只会调用自定义的构造/析构函数;
(3)构造和析构函数不需要返回值类型,构造函数可以带参或不带参,析构函数不带参;
(4)构造函数可以重载(overload),析构函数不需要重载;
(5)构造函数的名字就是类的名字,析构函数的名字是"~ + 类名";

3、为什么需要构造函数和析构函数

(1)在C语言中只有struct没有class,所以C语言没有构造/析构函数的概念,C语言程序员定义struct后,需要手动去给struct结构体成员初始化;
(2)C++是面向对象的语言,class的封装性比struct更好。
(3)比如:class中有个成员变量是指针,如果没有构造/析构函数,则需要定义对象后手动去为指针申请动态内存,在销毁对象前,手动去释放动态内存;现在动态内存的申请/释放可以放到构造/析构函数中,使用class的程序员不必再操心动态内存的申请释放;

4、不使用动态内存的构造/析构函数

4.1、示例代码

#include <iostream>

using namespace std;

class Person{
public:
    int age;

    string getName(void) const;

    //构造函数
    Person();
    Person(string myname);
    
	 // 析构函数
    ~Person();	

private:
    string name;    //人的名字
    mutable int getNameCnt; //名字被查询的次数

};


int main(void)
{
	//定义对象,此时会调用构造函数
	Person *p1 = new Person ("linux");

    cout << "p1.name=" << p1->getName() << endl;
	
    //   销毁对象
    delete(p1);

	return 0;
}

string Person::getName(void) const
{
    this->getNameCnt++;
    cout << "getNameCnt=" << this->getNameCnt << endl;
    return this->name;
}

//  使用参数列表的方式
Person::Person()
{
        cout << "Person::Person()" << endl;
        this->getNameCnt=0;
};

//  构造函数:使用参数列表的方式
Person::Person(string myname):name(myname)
{
       //this->name=myname;	//等同于上面参数列表的形式
        cout << "Person::Person(string myname):name(myname)" << endl;
        this->getNameCnt=0;
};

// 析构函数:在没有使用动态内存的情况下,析构函数一般都是空函数
Person::~Person()
{
      cout << "~Person" << endl;
};

4.2、代码分析

root@ubuntu:# ./app 
Person::Person(string myname):name(myname)
getNameCnt=1
p1.name=linux
~Person

(1)在定义对象时调用了构造函数,调用的是传string形式的,因为构造函数支持函数重载,并且定义定义对象时传入了string的参数;
(2)在销毁对象时调用了析构函数;

5、使用动态内存的构造/析构函数

5.1、示例代码

#include <iostream>

using namespace std;

class Person{
public:
    int age;

    string getName(void) const;

    //构造函数
    Person();
    Person(string myname);

     // 析构函数
    ~Person();

private:
    string *name;    //人的名字
    mutable int getNameCnt; //名字被查询的次数

};

int main(void)
{
    //定义对象,此时会调用构造函数
    Person *p1 = new Person ("linux");

    cout << "p1.name=" << p1->getName() << endl;

    //   销毁对象
    delete(p1);

    return 0;
}

string Person::getName(void) const
{
    this->getNameCnt++;
    cout << "getNameCnt=" << this->getNameCnt << endl;
    return *this->name;
}

//  使用参数列表的方式
Person::Person()
{
        cout << "Person::Person()" << endl;
        this->getNameCnt=0;
};

//  构造函数
Person::Person(string myname)
{
        this->name = new string(); //申请动态内存
        
       *this->name=myname;
        cout << "Person::Person(string myname):name(myname)" << endl;
        this->getNameCnt=0;
};

// 析构函数
Person::~Person()
{
      cout << "[~Person] delete this->name" << endl;
      delete (this->name);	//释放在构造函数中申请的动态内存
};

5.2、代码分析

root@ubuntu:# ./app 
Person::Person(string myname):name(myname)
getNameCnt=1
p1.name=linux
[~Person] delete this->name

(1)上第4节的代码相比,将class中name变量从string类型变成string指针类型;
(2)在构造函数中为string指针申请内存,在析构函数中释放内存;
总结:如果类中使用动态内存,可以在构造函数中申请,在析构函数中释放,使用类的程序员不用再操作内存的申请释放;

6、拷贝构造函数

参考博客:《【C++入门】拷贝构造函数》

7、推荐

我会在C++专栏持续根据更新C++相关的知识点,这里也给大家推荐一款学习C++的神器,我也是在用这一款神器在学习C++。
链接:学习神器跳转
如果你是想入门C++这门语言或者是找C++岗位的工作,都推荐你试试这个网站,里面有针对C++知识点的选择题、编程题,更有C++岗位的面试题
在这里插入图片描述
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++入门】(拷贝)构造函数和析构函数 的相关文章

随机推荐

  • linux编译mesa,编译安装 Mesa (OpenGL)

    最近因为工作需要 想看一下 OpenGL 的东西 就在笔记本上搭建了 OpenGL 的环境 解压后 运行 configure 根据提示安装必要的包 编译 安装 我安装到了 usr local private 下面 usr local pri
  • 佳威线管分级说明

    次次底级 keb sl刹车 次底 cgx sl刹车 lex sl变速 底级 无润滑 cex刹车 lex变速
  • Spark Task的各个动作时间来源以及Task Schedule Delay 问题排查

    背景 发现线上偶尔会出现一些Spark Task会显示Schedule Delay数分钟甚至十几分钟 所以要排查原因 Task 时间分析以及Schedule Delay计算公式 如图所示 时间轴上面的表示Driver 记录到的各个时间 时间
  • 结构体与共用体(联合体)

    参考 结构体与共用体 作者 一只青木呀 发布时间 2020 08 09 08 29 22 网址 https blog csdn net weixin 45309916 article details 107889394 参考 联合体 uni
  • 多线程下载

    原理 服务器cpu分配给每条线程的时间片是相同的 服务器带宽平均分配给每个线程 所以客户端开启的线程越多就能抢占到更多的服务器资源 用java实现 public class NultiDownload static String path
  • MySQL多表关系及多表查询

    多表关系 在关系型数据库中存在着三种多表关系 分别是一对多 多对一 多对多以及一对一 之所以会产生这些关系 是因为在进行数据设计的时候 分析得出业务之间存在着一定的关系 进而在数据中也就存在了这些关系 一对多 一对多是最基础的表间关系 意思
  • 给大家推荐一门比较适合用来学习流量分析技术的公开课(内附课程b站链接)

    最近看到同事在看一门课程 是CSNA出的一套免费对外公开课 跟着看了一下觉得不错 分享给大家 CSNA是国内比较老牌且低调的网络技术分析认证培训了 在网络运维和网络安全方向上还是有口皆碑的 课程内容比较体系化 有理论也有实操 涵盖了业务性能
  • php面试题猴子123报数(猴子选大王)

    题目就是有N个猴子 123循环报数数到3的猴子被踢出下一个接着报数 一遍一遍的循环直到剩余一个猴子 求这个猴子是最开始的第几号猴子 我想到了两个方法 第一个就是模拟报数的模式 每到3的时候unset一个元素 最后剩余的就是 要求的猴子 代码
  • windows如何关闭IIS (因为占用80端口而无法启动nginx)

    一 场景概述 正在写一个Web项目但是每次输入都需要加上端口号 所以想用服务器代理一下端口 让可以直接用nginx来解决这个问题但是 nginx异常无法打开 结果发现80端口被异常占用 因为windows的IIS也占用80端口号 比如win
  • 电脑命令教程计算机基础知识,电脑常用运行命令图文教程(DOS命令)

    本文介绍一些常用的运行窗口命令 也是DOS命令 同时所有的命令均在win7旗舰版测试通过 并附有运行后的图片 运行命令窗口如下 工具 原料 电脑一台 本文以win7系统的电脑为例 方法 步骤 1 调出运行命令窗口 按快捷键 win R 或者
  • java|8.18总结|基本功能

    1 思维导图 2 用自己的话描述某知识点是什么 举例 总结 一句话总结 环境变量 理解 环境变量相当于提前封装好一个环境 功能 在此环境下 比如在有path环境下 可以直接执行java文件 不用先进入JAVA的目录才能运行java 如果需要
  • 使用Docker安装配置Jupyter并配置R语言与Python环境

    文章目录 Docker docker的安装 将当前用户添加到docker用户组 拉取一个镜像 创建配置目录 启动docker服务 登录jupyter容器 安装vim 更换源 JupyterNotebook 设置python 安装Jupyte
  • 【burpsuite安全练兵场-服务端6】信息泄露漏洞-5个实验(全)

    前言 介绍 博主 网络安全领域狂热爱好者 承诺在CSDN永久无偿分享文章 殊荣 CSDN网络安全领域优质创作者 2022年双十一业务安全保卫战 某厂第一名 某厂特邀数字业务安全研究员 edusrc高白帽 vulfocus 攻防世界等平台排名
  • Vue中常用基础标签

    创建一个Vue实例 var vm new Vue el app data methods 在html中完整代码
  • 练习2-2 在不使用运算符&&或者

    1 for i 0 i lt lim 1 c getchar n c EOF i 2 s i c 3 4 5 while i lt lim 1 6 7 while c getchar EOF 8 9 while c getchar n 10
  • c语言基础总结之获取数组中元素最小值

    数组获取元素个数 sizeof ids sizeof int 需要根据字节的长度来计算个数 当然在java中直接 length来获取 c语言就是比较麻烦 毕竟java是封装语言 将繁杂的步骤分装好方便调用了 用随机数生成一个数组 写一个函数
  • Anaconda的安装与jupyter常用操作

    一 Anaconda的安装 关于Anaconda的在windows上的安装 我不做过多的赘述 大家可以参考博客 https ask hellobi com blog wangdawei 9786 这里 需要说明一下为什么选择Anaconda
  • 在虚拟机Docker安装MySQL8.0,Navicat连接数据库出错等踩过的坑

    Docker安装MySQL8 0 Navicat连接数据库 环境 虚拟机 CentOS 7 2 Docker 20 10 7 MySQL 8 0 27 安装MySQL 1 先创建两个MySQL使用文件夹 opt目录是Linux提供我们扩展的
  • 顺序表的定义和基本操作

    文章目录 顺序表的实现 静态分配 动态分配 顺序表的插入删除 顺序表的查找 总结 顺序表的实现 静态分配 include
  • 【C++入门】(拷贝)构造函数和析构函数

    1 构造函数和析构函数 1 构造函数 constructor 字面意思就是构造对象的函数 当我们定义类的对象时调用 可以帮我们完成对象的初始化 2 析构函数 destructor 可以看做是构造函数的逆过程 当销毁类的时候调用 做一些收尾的