C++ 八股文: 构造函数
什么是构造函数
构造函数(Constructor)是一种特殊的成员函数,用于在创建对象时进行初始化。它的作用是确保对象在创建后处于一个合法和可用的状态。构造函数在类定义中声明,其名称与类名相同,但不带返回类型。
写一个拷贝构造函数?为什么你写的是引用传递?而不是值传递?(除了效率上的问题外)
拷贝构造函数用于创建一个对象的拷贝,通常在以下情况下使用:
- 通过值传递方式将对象传递给函数。
- 通过值返回方式从函数返回对象。
- 在创建一个对象作为另一个对象的拷贝时(如对象初始化或赋值)。
拷贝构造函数通常使用引用传递,而不是值传递,因为值传递会导致对象的无限递归复制,陷入无限循环。这是因为拷贝构造函数本身会创建一个新对象,如果将参数传递给拷贝构造函数时使用值传递,会导致无限递归的拷贝。
以下是一个示例拷贝构造函数,使用引用传递参数:
class MyObject {
public:int value;// 拷贝构造函数MyObject(const MyObject& other) {value = other.value;}
};int main() {MyObject obj1;obj1.value = 42;// 通过拷贝构造函数创建 obj2 作为 obj1 的拷贝MyObject obj2 = obj1;// obj1 和 obj2 现在有相同的值std::cout << obj1.value << " " << obj2.value << std::endl;return 0;
}
在上述示例中,拷贝构造函数 MyObject(const MyObject& other)
接受一个引用参数,这样可以避免无限递归的拷贝。如果我们将参数改为值传递,将导致无限循环的拷贝,直到栈溢出。
除了效率问题,使用引用传递还可以避免不必要的资源分配和释放。通过引用传递,只是传递了对象的引用而不是整个对象的拷贝,因此效率更高。此外,使用引用传递也更符合对象的语义,因为拷贝构造函数的目的是创建一个新对象,而不是复制对象的所有内容。所以,使用引用传递是一种更好的做法。
构造函数重载:
-
作用:
- 初始化对象的成员变量。
- 分配和管理资源,如内存分配、文件打开、数据库连接等。
- 执行其他必要的初始化操作。
-
语法:
class ClassName { public:// 默认构造函数(无参数)ClassName() {// 构造函数的实现}// 带参数的构造函数ClassName(Type1 param1, Type2 param2, ...) {// 构造函数的实现} };
构造函数的语法示例中:
ClassName
是类的名称。public
部分用于指定构造函数的访问权限,通常是公共的,以允许外部代码创建对象。- 构造函数的名称与类名相同。
- 可以定义多个构造函数,每个构造函数具有不同的参数列表,允许不同的对象初始化方式。
为什么构造函数不能为虚函数?
构造函数不能为虚函数的原因是与对象的创建和初始化顺序以及虚函数机制有关。虚函数的特性和构造函数的执行顺序之间存在矛盾,因此构造函数不能被声明为虚函数。以下是相关的解释:
-
对象的初始化顺序:对象的初始化是按照继承层次从基类到派生类的顺序进行的。首先,基类的构造函数被调用,然后依次调用派生类的构造函数。这个初始化顺序是固定的。
-
虚函数的调用依赖于对象的类型:虚函数的调用是依赖于对象的类型的,而不是对象的构造过程。当对象被创建时,它在构造函数内部还没有完全初始化,因此对象的类型可能尚未被确定。虚函数调用要等到对象完全初始化后才有意义。
由于构造函数在对象的初始化阶段执行,而虚函数的调用依赖于对象的完全初始化,将构造函数声明为虚函数会导致潜在问题:
- 构造函数声明为虚函数会导致不确定性,因为在构造函数内部,对象的类型可能还不确定,虚函数调用可能会指向错误的实现。
- 基类构造函数的调用是在派生类构造函数之前发生的,因此派生类的虚函数表尚未完全设置,使得虚函数无法正确调用。
-
class Base { public:virtual void foo() {// 虚函数}Base() {foo(); // 构造函数中调用虚函数} };class Derived : public Base { public:void foo() override {// 派生类的虚函数实现} };
在这个示例中,如果
Base
的构造函数声明为虚函数,那么在调用foo()
时,派生类的虚函数实现还没有生效,因此无法调用正确的虚函数。这是为什么构造函数不能为虚函数的一个示例。总之,构造函数不能声明为虚函数,因为虚函数的调用依赖于对象的完全初始化,而构造函数的目标是初始化对象。为了避免潜在的问题和不确定性,最好将构造函数保持为普通的成员函数,而将虚函数用于对象完全初始化后的多态操作。
构造函数使用private
将构造函数声明为private
是一种封装技巧,它通常用于实现单例模式、工厂模式或其他只允许有限途径创建对象的情况。当构造函数被声明为private
时,只有类内部的函数可以访问它,外部代码无法直接创建类的实例。
下面是一个示例,展示了如何将构造函数声明为private
:
class Singleton {
public:// 获取唯一的实例static Singleton& getInstance() {static Singleton instance; // 在首次调用时创建唯一的实例return instance;}// 其他成员函数void doSomething() {// 执行操作}private:// 构造函数私有,防止外部代码直接创建对象Singleton() {// 构造函数的实现}// 防止复制和赋值操作Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;
};
在上述示例中,构造函数Singleton()
被声明为private
,防止外部代码直接创建Singleton
类的实例。相反,通过公共的静态成员函数getInstance()
来获取唯一的实例。这确保了只有一个Singleton
对象存在。
通过将构造函数声明为private
,你可以实现更严格的对象创建控制,确保对象的唯一性,同时提供一个公共的方法来获取实例。这在单例模式等情况下非常有用。
构造函数的初始化列表和构造函数体内的赋值操作之间有一些重要的区别:
-
执行时间:
- 初始化列表:构造函数初始化列表在进入构造函数体之前执行。这意味着它们在对象的成员变量构造之前执行,可以在构造函数体内访问这些成员变量。
- 构造函数体内的赋值:赋值操作在构造函数体内执行,因此它们在对象的成员变量已经构造之后执行。这意味着它们不能在构造函数体内初始化成员变量。
-
效率:
- 初始化列表:使用初始化列表通常更高效,因为它直接初始化成员变量,而不是先默认初始化然后再赋值。
- 构造函数体内的赋值:在构造函数体内赋值需要两步操作:首先默认初始化成员变量,然后再进行赋值操作,可能会引入额外的开销。
-
成员变量的类型:
- 初始化列表:适用于非静态成员变量和const成员变量,以及基本类型(如int、double)。
- 构造函数体内的赋值:在构造函数体内可以用于更多的情况,包括对非const成员变量、静态成员变量和复杂类型(如类对象)的初始化。
-
顺序:
- 初始化列表:允许你指定成员变量的初始化顺序,即使它们在类中的声明顺序不同。这有助于避免潜在的问题,如依赖于初始化顺序的成员变量之间的问题。
- 构造函数体内的赋值:通常依赖于成员变量的声明顺序,因此如果声明顺序与所需初始化顺序不同,可能需要小心。
综上所述,初始化列表通常是更好的选择,特别是对于非静态和const成员变量。它提供了更高效的初始化方法,更好的控制初始化顺序,以及更清晰的代码结构。但对于其他情况,如在构造函数体内需要进行复杂的计算或条件判断来确定成员变量的值,构造函数体内的赋值操作可能更合适。
相关文章:
C++ 八股文: 构造函数
什么是构造函数 构造函数(Constructor)是一种特殊的成员函数,用于在创建对象时进行初始化。它的作用是确保对象在创建后处于一个合法和可用的状态。构造函数在类定义中声明,其名称与类名相同,但不带返回类型。 写一个…...

自动切割短视频的软件推荐,一键生成1000条短视频,支持六大主流平台矩阵分发,快来免费试用
经过小编的多方测评,今天给大家推荐一款性价比、好评率、专业性全都超高的软件——超级编导批量剪辑软件,更重要的是这款软件支持免费试用,一起来看看超级编导如何帮助大家自动分割视频的吧。 复制视频链接,一键上传视频素材后&am…...

从零开始学习秒杀项目
构思了很多种讲述这个简易版的秒杀项目的思路,比如按照功能分类,按照项目亮点串起来讲述,总觉得不适合基础薄弱的同学来学习,所以本项目按照从搭建开始,过程中需要什么来学习什么。 技术栈 SpringBootmybatisPlus&am…...

儿童珠宝首饰上亚马逊美国站合规标准是什么?如何办理?
儿童珠宝首饰 儿童珠宝首饰指原则上由 12 岁及以下儿童作为装饰品移除或穿戴的商品。本政策涵盖的儿童珠宝首饰,包括但不限于脚链、手链、耳环、项链、戒指、珠宝首饰制作或维修套装以及钟表。 亚马逊儿童珠宝首饰政策 亚马逊要求所有儿童珠宝首饰均经过检测并符合…...
ORACLE 19C PDB FOR MYSQL 5.7 部署ogg
一、--软件配置 角色 数据库/软件版本 OGG版本 IP ---------- ----------------- ------------------------------- ----------- 源端服务器 Oracle Datbase 19 Oracle C##GOLDENGATE 19.1.0.0.4 10.10.10.32 目标服务器 MYSQ…...
前端 html 中的 meta 标签有哪些用处?
HTML中的<meta>标签用于提供有关文档的元数据(metadata),它们不会在页面上显示出来,而是提供有关页面的信息,使搜索引擎和浏览器能够更好地理解和使用文档。下面是一些常见的用途: 1、指定文档的字符…...

罗技鼠标接收器丢失或损坏后用另一个接收器配对的方法
本文介绍罗技鼠标在丢失、损坏其自身原有的接收器后,将另一个新的接收器与原有鼠标相互配对的方法。 在开始之前,大家需要首先查看两个内容:首先是原有的鼠标——大家需要查看自己的鼠标(罗技键盘也是同样的操作)底部&…...
Python语法
文章目录 一、Python基础1. 数据类型和变量2. 字符串和编码字符编码Python的字符串格式化 3. list和tuplelisttuple 4.条件判断5. 模式匹配6. 循环7. dict 和 setdictset 二、函数1. 调用函数2. 定义函数3. 函数的参数4. 递归函数 三、高级特性四、函数式编程1. 高阶函数2. 返回…...

电脑经营商城小程序的作用是什么
电脑是企业办公必备的工具,同时很多家庭都有配备,无论笔记本还是台式在各场景中应用都非常广泛,市场各类品牌也很多,区别于以前店内购买,现在不少消费者会选择线上电商平台购买,也因此如今电脑经销商或品牌…...

森海塞尔EW-DP SKP直插式发射机:真正的无失真录制
韦德马克,2023年9月15日 – 10月底,EW-DP系列将再添新品——EW-DP SKP直插式发射机,面向摄像师、广播电视公司和电影制作人。板载32位浮点录制,结合该系列领先的134 dB发射机动态范围,让音频失真不复存在。无论要在现场…...
通过小程序实现会议Oa的会议展示以及个人中心
🏅我是默,一个在CSDN分享笔记的博主。📚📚 🌟在这里,我要推荐给大家我的专栏《微信小程序 》。🎯🎯 🚀无论你是编程小白,还是有一定基础的程序员,…...

STM32驱动GY-39监测环境温度,湿度,大气压强,光强度
目录 模块简介模块测试接线代码测试现象 总结 模块简介 GY-39 是一款低成本,气压,温湿度,光强度传感器模块。工作电压 3-5v,功耗小,安装方便。 其工作原理是,MCU 收集各种传感器数据,统一处理&…...

在华为和比亚迪干了5年测试,月薪25K,熬夜总结出来的划水经验.....
先简单交代一下背景吧,某不知名 985 的本硕,17 年毕业加入华为,之后跳槽到了比亚迪,一直从事软件测试的工作。之前没有实习经历,算是5年的工作经验吧。 这5年之间完成了一次晋升,换了一家公司,…...
Mac 使用 scp 上传或下载文件/文件夹
目录 上传文件到远程服务器 scp 本地文件路径 远程用户名远程IP:远程目标目录上传文件夹到远程服务器 scp -r 本地文件夹 远程用户名远程IP:远程目标目录从远程服务器下载文件 scp 远程用户名远程IP:远程文件路径 本地目标目录从远程服务器下…...

Restful 风格
目录 Restful风格创建springboot项目SpringMVC开发Restful接口1、获取所有的员工思路代码RequestMappingGetMapping 2、获取单个员工思路代码注意: 3、删除员工数据思路:代码单个删除批量删除 4、更新员工数据思路: 5、jQuery发送请求发送del…...

LLM 系列 | 21 : Code Llama实战(上篇) : 模型简介与评测
引言 小伙伴们好,我是《小窗幽记机器学习》的小编:卖热干面的小女孩。 个人CSDN首页:JasonLiu1919_面向对象的程序设计,深度学习,C-CSDN博客 今天开始以2篇小作文介绍代码大语言模型Code Llama。上篇主要介绍Code Llama的基本情况并基于Hug…...

积分球荧光光谱测试光电检测方式有哪些优点?
积分球荧光光谱测试是一种测量光通量的方法,其基本原理是将待测光源放入积分球中,在积分球内壁涂以白色漫反射层,光源发出的光经球壁多次反射后,使整个球壁上的照度均匀分布,再通过球壁上的孔投射到光电探测器上的光通…...

软考考试时间已出!采用连考形式!
2023年下半年计算机技术与软件专业技术资格(水平)考试批次安排已出!下面是具体的考试安排。 通知原文如下:↓↓↓ 按照《2023年下半年计算机技术与软件专业技术资格(水平)考试有关工作调整的通告》&#x…...

深入理解强化学习——学习(Learning)、规划(Planning)、探索(Exploration)和利用(Exploitation)
分类目录:《深入理解强化学习》总目录 学习 学习(Learning)和规划(Planning)是序列决策的两个基本问题。 如下图所示,在强化学习中,环境初始时是未知的,智能体不知道环境如何工作&a…...
大模型LLM相关面试题整理-训练集-训练经验-微调
3 大模型(LLMs)微调 3.1 如果想要在某个模型基础上做全参数微调,究竟需要多少显存? 要确定全参数微调所需的显存量,需要考虑以下几个因素: 模型的大小:模型的大小是指模型参数的数量。通常&…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...
Spring Boot + MyBatis 集成支付宝支付流程
Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例(电脑网站支付) 1. 添加依赖 <!…...