当前位置: 首页 > news >正文

[C++]六大默认成员函数详解

☃️个人主页:fighting小泽
🌸作者简介:目前正在学习C++和Linux
🌼博客专栏:C++入门
🏵️欢迎关注:评论👊🏻点赞👍🏻留言💪🏻

文章目录

  • 1.类的6个默认成员函数
  • 2.构造函数
    • 2.1 概念
    • 2.2 特性
  • 3.析构函数
    • 3.1 概念
    • 3.2 特性
  • 4.拷贝构造函数
    • 4.1 概念
    • 4.2 特征
  • 5.赋值运算符重载
    • 5.1 运算符重载
    • 5.2 赋值运算符重载
    • 5.3 前置++和后置++重载
  • 6.const成员
    • 7.取地址及const取地址操作符重载

1.类的6个默认成员函数

如果一个类中什么都没有,简称空类。
但它并不是什么都没有,任何类在什么都不写的情况下,编译器会自动生成以下6个默认成员函数。
默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

class Date {};

在这里插入图片描述

2.构造函数

2.1 概念

对于以下Date类:

 class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;d1.Init(2022, 7, 5);d1.Print();Date d2;d2.Init(2022, 7, 6);d2.Print();return 0;
}

对于Date类可以通过类中的函数Init给对象设置日期,但如果每次创建对象时都调用该方法设置信息,未免有点麻烦,那能否在对象创建时,就将信息设置进去呢?

构造函数可以在创建对象时给它一个合适的初始值,并且在对象整个生命周期内只调用一次。

2.2 特性

构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象

其特征如下:

  1. 函数名与类名相同。
  2. 无返回值。
  3. 对象实例化时编译器自动调用对应的构造函数。
  4. 构造函数可以重载。
  class Date{public:// 1.无参构造函数Date(){}// 2.带参构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;};void TestDate(){Date d1; // 调用无参构造函数Date d2(2015, 1, 1); // 调用带参的构造函数// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明// 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象// warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)Date d3();}
  1. 如果类中没有显示定义的构造函数,则C++编译器会自动生产一个无参的默认构造函数,一旦用户显示定义编译器将不再生成。(拷贝构造是构造函数)

  2. C++把类型分为内置类型和自定义类型,内置类型成员编译器生成的默认构造函数不会对它初始化,是随机值(大多数编译器会给它初始化,但语法中没有规定)。而自定义类型,编译器会去调用它的默认构造函数。(C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在类中声明时可以给默认值。)

  3. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
    注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数

3.析构函数

3.1 概念

析构函数与构造函数功能相反,编译器销毁局部对象的时候,对象会自动调用析构函数,清理对象中的资源。

3.2 特性

析构函数是特殊的成员函数,其特征如下:

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数无返回值类型。
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。
  5. 关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器生成的默认析构函数,对自定类型成员调用它的析构函数。
class Time
{
public:~Time(){cout << "~Time()" << endl;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year = 1970;int _month = 1;int _day = 1;// 自定义类型Time _t;
};
int main()
{Date d;return 0;
}
// 程序运行结束后输出:~Time()
// 在main方法中根本没有直接创建Time类的对象,为什么最后会调用Time类的析构函数?
// 因为:main方法中创建了Date对象d,而d中包含4个成员变量,其中_year, _month, _day三个是
// 内置类型成员,销毁时不需要资源清理,最后系统直接将其内存回收即可;而_t是Time类对象,所以在
// d销毁时,要将其内部包含的Time类的_t对象销毁,所以要调用Time类的析构函数。但是:main函数
// 中不能直接调用Time类的析构函数,实际要释放的是Date类对象,所以编译器会调用Date类的析构函
// 数,而Date没有显式提供,则编译器会给Date类生成一个默认的析构函数,目的是在其内部调用Time
// 类的析构函数,即当Date对象销毁时,要保证其内部每个自定义对象都可以正确销毁
// main函数中并没有直接调用Time类析构函数,而是显式调用编译器为Date类生成的默认析构函数
// 注意:创建哪个类的对象则调用该类的析构函数,销毁那个类的对象则调用该类的析构函数
  1. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。

4.拷贝构造函数

4.1 概念

拷贝构造函数用来位已存在的自定义型对象创建一个与原对象相同的新对象。创建时由编译器自动调用。

4.2 特征

拷贝构造函数也是特殊的成员函数,其特征如下:

  1. 拷贝构造函数是构造函数的一个重载形式
  2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
 Date(const Date& d)   {_year = d._year;_month = d._month;_day = d._day;}
  1. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
  2. 注意:在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定义类型是调用其拷贝构造函数完成拷贝的

类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

5.拷贝构造函数典型调用场景:

  • 使用已存在对象创建新对象
  • 函数参数类型为类类型对象
  • 函数返回值类型为类类型对象
class Date
{
public:Date(int year, int minute, int day){cout << "Date(int,int,int):" << this << endl;}Date(const Date& d){cout << "Date(const Date& d):" << this << endl;}~Date(){cout << "~Date():" << this << endl;}
private:int _year;int _month;int _day;
};
Date Test(Date d)
{Date temp(d);return temp;
}
int main()
{Date d1(2022,1,13);Test(d1);return 0;
}

为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用尽量使用引用。

5.赋值运算符重载

5.1 运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)

注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
  • .* :: sizeof ?: . 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。
    // bool operator==(Date* this, const Date& d2)// 这里需要注意的是,左操作数是this,指向调用函数的对象bool operator==(const Date& d2){return _year == d2._year;&& _month == d2._month&& _day == d2._day;}

5.2 赋值运算符重载

  1. 赋值运算符重载格式
  • 参数类型:const T&,传递引用可以提高传参效率
  • 返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
  • 检测是否自己给自己赋值
  • 返回*this :要复合连续赋值的含义
Date& operator=(const Date& d){if(this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}
  1. 赋值运算符只能重载成类的成员函数不能重载成全局函数
// 赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数
Date& operator=(Date& left, const Date& right)
{if (&left != &right){left._year = right._year;left._month = right._month;left._day = right._day;}return left;
}
// 编译失败:
// error C2801: “operator =”必须是非静态成员

原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。

  1. 用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。

注意:如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理则必
须要实现。

5.3 前置++和后置++重载

 // 前置++:返回+1之后的结果// 注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率Date& operator++(){_day += 1;return *this;}// 后置++:// 前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载// C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递// 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存一份,然后给this+1//而temp是临时对象,因此只能以值的方式返回,不能返回引用Date operator++(int){Date temp(*this);_day += 1;return temp;}

6.const成员

将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

在这里插入图片描述

7.取地址及const取地址操作符重载

这两个默认成员函数一般不用重新定义 ,编译器默认会生成。

class Date
{ 
public :
Date* operator&()
{return this ;
}
const Date* operator&()const
{return this ;
}
private :int _year ; // 年int _month ; // 月int _day ; // 日
};

};
这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容!

相关文章:

[C++]六大默认成员函数详解

☃️个人主页&#xff1a;fighting小泽 &#x1f338;作者简介&#xff1a;目前正在学习C和Linux &#x1f33c;博客专栏&#xff1a;C入门 &#x1f3f5;️欢迎关注&#xff1a;评论&#x1f44a;&#x1f3fb;点赞&#x1f44d;&#x1f3fb;留言&#x1f4aa;&#x1f3fb; …...

组合(回溯算法)

77. 组合 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 样例输入 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],…...

力扣:1419. 数青蛙

题目&#xff1a; 代码&#xff1a; class Solution { public:int minNumberOfFrogs(string croakOfFrogs){string s "croak";int ns.size();//首先创建一个哈希表来标明每个元素出现的次数&#xff01;vector<int>hash(n); //不用真的创建一个hash表用一个数…...

java_springboot企业人事考勤请假管理信息系统rsglxx+jsp

&#xff08;1&#xff09;熟练掌握Java开发的原理和方法 &#xff08;2&#xff09;熟练学习掌握SSM框架 &#xff08;3&#xff09;熟悉软件开发的流程 &#xff08;4&#xff09;了解中内外互联网中所主流的技术 &#xff08;5&#xff09;深层次的了解计算机学科领域的知识…...

java项目之木里风景文化管理平台(ssm+vue)

项目简介 木里风景文化管理平台实现了以下功能&#xff1a; 前台功能&#xff1a;用户进入系统可以实现首页&#xff0c;旅游公告&#xff0c;景区&#xff0c;景区商品&#xff0c;景区美食&#xff0c;旅游交通工具&#xff0c;红黑榜&#xff0c;个人中心&#xff0c;后台…...

源码安装mysql

使用源码安装mysql&#xff0c;这里选择的版本是mysql5.7.35 ,系统是Centos7.6 官网下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 下载源码压缩包 [rootlocalhost ~]# cd /opt[rootlocalhost opt]# wget https://downloads.mysql.com/archives/get/…...

注解方式优雅的实现Redisson分布式锁

1.前言 随着微服务的快速推进&#xff0c;分布式架构也得到蓬勃的发展&#xff0c;那么如何保证多进程之间的并发则成为需要考虑的问题。因为服务是分布式部署模式&#xff0c;本地锁Reentrantlock和Synchnorized就无法使用了&#xff0c;当然很多同学脱口而出的基于Redis的se…...

服务器安装JDK17 版本显示JDK8

服务器之前安装的是JDK8&#xff0c;后面升级JDK17后&#xff0c;发现执行 java -vsrsion 显示的是此时我的环境变量已经换成了JAVA17的路径 输入&#xff1a; vim /etc/profile 解决办法&#xff1a; 1.更新自己环境变量 bash export JAVA_HOME/usr/local/jdk-17.0.7 …...

利用MCMC 获得泊松分布

写出概率流方程如下 if state 0: if np.random.random() < min([Lambda/2, 1]):state 1else:passelif state 1:if choose_prob_state[i] < 0.5:#选择 1 -> 0&#xff0c;此时的接受概率为min[2/Lambda, 1]if np.random.random() < min([2/Lambda, 1]…...

docker-compose脚本编写及常用命令

安装 linux DOCKER_CONFIG/usr/local/lib/docker/cli-plugins sudo mkdir -p $DOCKER_CONFIG/cli-plugins sudo curl -SL https://521github.com/docker/compose/releases/download/v2.6.1/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose sudo c…...

编译企业微信会话内容存档PHP版SDK扩展

1.下载SDK 如果克隆不了&#xff0c;就页面下载 git clone https://github.com/pangdahua/php7-wxwork-finance-sdk2.下载企微官网C版本的最新sdk文件 下载地址&#xff1a;https://wwcdn.weixin.qq.com/node/wework/images/sdk_20201116.rar 下载以后将解压之后的文件夹里l…...

传统算法:使用 Pygame 实现K-Means 聚类算法

使用 Pygame 模块演示了 K-Means 聚类算法的基本原理。让我逐步解释它的实现: 初始化和基本设置 Pygame 初始化: 通过 pygame.init() 初始化 Pygame。 定义颜色和屏幕大小: 定义了一些颜色常量(WHITE, BLACK, RED, GREEN, BLUE)和屏幕的宽度和高度。 创建 Pygame 窗口:…...

WebUI工作流插件超越ComfyUI

在AI绘画领域&#xff0c;Stable Diffsion是最受欢迎的&#xff0c;因为它是开源软件。 开源有两大优势&#xff0c;一是免费&#xff0c;二是适合折腾。 大量的开发者、爱好者投入无尽的热情&#xff0c;来推动Stable Diffsion的快速发展。 在图形界面方面&#xff0c;WebU…...

Docker容器化平台及其优势和应用场景介绍

Docker是一种开源的容器化平台&#xff0c;它基于操作系统级别虚拟化技术&#xff0c;可以将应用程序及其依赖项打包成一个独立的容器&#xff0c;提供轻量级、一致性、可移植性的应用环境。Docker的基本概念和优势如下&#xff1a; 镜像(Image)&#xff1a;Docker容器的基础&…...

Hive:从HDFS回收站恢复被删的表

场景 一张手工维护的内部表&#xff0c;本来排查没有使用&#xff0c;然后删掉了&#xff0c;发现又需要使用&#xff0c;只能恢复这张表了。 1.确认HDFS是否开启回收站功能 2.查看回收站中的数据 被删除的数据会放在删除数据时使用的用户目录下&#xff0c;如&#xff1a;使…...

TZOJ 1387 人见人爱A+B

答案&#xff1a; #include <stdio.h> void time(int ah, int am, int as, int bh, int bm, int bs, int* sum_h, int* sum_m, int* sum_s) //不需要返回值所以定义void函数&#xff0c;前面6个为输入&#xff0c;然后用指针存给后面三个 {*sum_s (as bs) % 60; …...

校园圈子系统丨交友丨地图找伴丨二手市场等功能丨源码交付支持二开丨APP小程序H5三端交付!

校园圈子系统是一款专为校园生活设计的智能应用&#xff0c;拥有丰富多样的功能模块&#xff0c;提供全方位的服务。无论您是师生还是校友&#xff0c;我们都为您打造了一个与校园紧密相连的交流平台。 通过校园圈子系统&#xff0c;您可以方便地浏览校内最新动态&#xff0c;包…...

java操作windows系统功能案例(一)

下面是一个Java操作Windows系统功能的简单案例&#xff1a; 获取系统信息&#xff1a; import java.util.Properties;public class SystemInfo {public static void main(String[] args) {Properties properties System.getProperties();properties.list(System.out);} }该程…...

【双向链表的实现】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 1. 双向链表的结构 2. 双向链表的实现 2.1 头文件 ——双向链表的创建及功能函数的定义 2.2 源文件 ——双向链表的功能函数的实现 2.3 源文件 ——双向链表功能的…...

中台战略思想与架构总结

中台战略思想与架构总结 在2015年年中&#xff0c;马云带领阿里高管&#xff0c;拜访了游戏公司Supercell&#xff0c;以《部落战争》《海岛奇兵》《卡通农场》等游戏知名。 Supercell是一家典型的以小团队模式进行游戏开发的公司&#xff0c;一般来说两个员工&#xff0c;或…...

不止于上传预览:在若依框架中构建一个轻量级企业文档管理模块

若依框架下的企业级文档中心设计与实战 在数字化转型浪潮中&#xff0c;企业文档管理正从简单的文件存储向智能化协作平台演进。基于若依微服务框架构建文档中心模块&#xff0c;不仅能满足基础的PDF上传预览需求&#xff0c;更能为企业提供版本控制、权限管理、全文检索等进阶…...

解决Swagger2集成中v2/api-docs接口404问题的关键:正确配置Docket分组

1. 为什么访问v2/api-docs会返回404&#xff1f; 这个问题困扰过不少开发者。当你兴冲冲地集成完Swagger2&#xff0c;打开swagger-ui.html页面&#xff0c;却发现页面一片空白&#xff0c;控制台报错显示v2/api-docs接口返回404。更让人抓狂的是&#xff0c;单独访问这个接口时…...

发那科机器人开机必看:示教器不亮时的3种紧急处理方案(含数据保护技巧)

发那科机器人开机必看&#xff1a;示教器不亮时的3种紧急处理方案&#xff08;含数据保护技巧&#xff09; 当生产线上的发那科机器人示教器突然无法点亮时&#xff0c;设备管理员往往面临巨大压力。这种故障不仅会中断生产流程&#xff0c;还可能因不当操作导致关键数据丢失。…...

DETR训练避坑大全:Windows10+PyCharm环境下的5个常见报错解决方案

DETR实战指南&#xff1a;Windows 10环境下的5大典型问题深度解析与解决方案 在目标检测领域&#xff0c;DETR&#xff08;Detection Transformer&#xff09;作为首个完全基于Transformer架构的端到端检测系统&#xff0c;正在改变传统计算机视觉任务的实现方式。不同于Faste…...

从ROS1到ROS2:手把手教你移植hdl_localization激光点云定位包(含完整CMakeLists.txt修改指南)

从ROS1到ROS2&#xff1a;激光点云定位包的现代化移植实战指南 激光SLAM技术正在经历从ROS1到ROS2的范式迁移浪潮。作为核心定位算法之一&#xff0c;hdl_localization的移植不仅是构建系统的转换&#xff0c;更是一次架构思维的升级。本文将带您深入理解ament_cmake的模块化设…...

概率论其实很简单:从“明天会不会下雨”到“AI怎么猜你心思”

一、概率就是“长期来看&#xff0c;这件事发生的比例”你早上看天气预报&#xff0c;说“降水概率30%”。你心想&#xff1a;才30%&#xff0c;不带了伞。结果下午淋成落汤鸡。你骂天气乱报&#xff1f;不用。因为30%的意思是&#xff1a;如果像今天这样的天气有100天&#xf…...

MediaPipe模型离线部署与本地Demo实战指南

1. MediaPipe模型离线部署全攻略 遇到MediaPipe模型下载失败的问题&#xff0c;相信不少开发者都踩过这个坑。特别是在内网环境或者网络不稳定的情况下&#xff0c;官方自动下载功能经常无法正常工作。我去年在给某制造企业部署智能质检系统时就遇到过类似情况&#xff0c;他们…...

终极指南:QLVideo让macOS视频预览支持200+格式,Finder管理效率提升300%

终极指南&#xff1a;QLVideo让macOS视频预览支持200格式&#xff0c;Finder管理效率提升300% 【免费下载链接】QuickLookVideo This package allows macOS Finder to display thumbnails, static QuickLook previews, cover art and metadata for most types of video files. …...

用STM32F103C8T6和NRF24L01自制遥控器,从硬件选型到代码调试的完整避坑指南

STM32F103C8T6与NRF24L01遥控器开发实战&#xff1a;从硬件设计到软件调试的全流程解析 在创客和嵌入式开发领域&#xff0c;无线遥控系统一直是热门话题。无论是机器人控制、无人机飞行还是智能家居应用&#xff0c;稳定可靠的遥控器都是不可或缺的核心组件。本文将详细介绍如…...

AI赋能运维:基于快马平台打造智能域名故障诊断与修复建议助手

最近在维护公司网站时遇到了新老域名切换导致的访问故障&#xff0c;传统排查流程需要手动分析日志、逐个测试可能原因&#xff0c;效率很低。这次尝试用InsCode(快马)平台的AI能力搭建了一个智能诊断工具&#xff0c;效果超出预期。分享下具体实现思路和关键环节&#xff1a; …...