c++ 构造函数详细介绍

c++对象的创建

c++对象的创建一般分为以下三个阶段:

  1. 分配内存:
    ■ 在堆区、栈区或者全局数据区留出足够多的字节。这个时候的内存还比较“原始”,没有被“教化”,它所包含的数据一般是零值或者随机值,没有实际的意义;
    ■ 这通常是通过使用 new 运算符动态分配内存或者在栈上为对象分配内存空间。
  2. 初始化:
    ■ 初始化就是首次对内存赋值,让它的数据有意义。注意是首次赋值,再次赋值不叫初始化。初始化的时候还可以为对象分配其他的资源(如动态分配内存等),或者提前进行一些计算等。初始化就是调用构造函数。
    ■ 在构造函数中,可以使用成员初始化列表(Member Initialization List)或构造函数体内的赋值语句来初始化成员变量。这些初始化操作将对象的成员变量设置为适当的值。
  3. 返回对象地址:
    在构造函数执行完毕后,对象的地址将被返回给对象的引用或指针,使得可以通过该引用或指针访问和操作对象。

c++ 构造函数

C++ 构造函数(Constructor)是一种特殊的成员函数,用于创建和初始化类的对象。构造函数在对象创建时自动调用,并负责为对象的成员变量赋予初始值。

构造函数的分类:

构造函数类别解释
默认构造函数(Default Constructor)创建类的时候没有写构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做;
参数化构造函数(Parameterized Constructor)带有参数的构造函数,用于根据提供的参数值进行对象的初始化。参数化构造函数允许在创建对象时传递不同的参数,以便根据参数值初始化对象的成员变量。也可以理解伟重载构造函数
拷贝构造函数(Copy Constructor)接受同类型对象作为参数的构造函数,用于创建新对象并将传递的对象的值复制到新对象中。拷贝构造函数常用于对象的复制和创建对象副本。 若没有显示的写复制构造函数,则系统会默认创建一个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险。
移动构造函数(Move Constructor)接受同类型对象的右值引用作为参数的构造函数,用于创建新对象并从传递的对象中“移动”资源(如动态分配的内存)到新对象中。移动构造函数常用于提高性能和资源管理。
类型转换构造函数(Conversion Constructor)一种特殊的构造函数,用于将一种类型的对象转换为另一种类型的对象。它允许在需要时隐式地进行类型转换,或者通过显式构造函数调用进行显式类型转换。

默认构造函数:

C++ 默认拷贝构造函数(Default Copy Constructor)是编译器自动生成的构造函数,用于执行对象的浅拷贝(shallow copy)。如果在类中没有显式定义拷贝构造函数,编译器会自动生成默认的拷贝构造函数。

默认拷贝构造函数的特点如下:

  • 接受同类型对象的常量引用作为参数。
  • 执行逐个成员变量的复制操作,将传递的对象的值复制到新对象中的对应成员变量。
  • 对于指针成员变量,执行浅层复制,即复制指针的值而不是复制指针指向的数据。
class MyClass {
public:int data;int* ptr;// 默认构造函数MyClass() {data = 0;ptr = new int(0);}// ...
};

上述示例中,如果没有显式定义拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数。该默认拷贝构造函数将执行浅层复制,即复制 data 的值和 ptr 的指针值。

使用默认拷贝构造函数可以进行对象的浅拷贝,即复制对象的成员变量的值。但对于指针类型的成员变量,浅拷贝可能会导致多个对象共享同一块内存,从而引发潜在的问题。如果需要执行深层复制或资源管理,通常需要显式定义自定义的拷贝构造函数。

参数化构造函数:

C++ 参数化构造函数(Parameterized Constructor)是一种构造函数,接受参数用于在对象创建时进行自定义的初始化操作。通过参数化构造函数,可以根据提供的参数值来初始化对象的成员变量。

参数化构造函数的特点如下:

  • 接受一个或多个参数,用于传递初始化所需的值。
  • 参数个数、类型和顺序要与构造函数的声明相匹配。
  • 可以根据需求定义多个不同的参数化构造函数,以提供不同的初始化方式。
class MyClass {
public:int data;// 默认构造函数MyClass() {data = 0;}// 参数化构造函数MyClass(int value) {data = value;}
};

通过参数化构造函数,我们可以在创建对象时传递不同的参数值,以便根据参数值初始化对象的成员变量。例如:

MyClass obj1;          // 调用默认构造函数创建对象 obj1,data = 0
MyClass obj2(42);      // 调用参数化构造函数创建对象 obj2,data = 42

拷贝构造函数:

C++ 拷贝构造函数(Copy Constructor)是一种特殊的构造函数,用于创建新对象并将另一个同类型对象的值复制到新对象中。拷贝构造函数通常用于对象的复制和创建对象副本。

拷贝构造函数的特点如下:

  • 接受同类型对象的常量引用作为参数;它只有一个参数,即参数类型是本类的引用。
  • 用于创建新对象,并将传递的对象的值复制到新对象中。
  • 对于指针成员变量,默认情况下执行浅层复制,即复制指针的值而不是复制指针指向的数据。
class MyClass {
public:int data;int* ptr;// 默认构造函数MyClass() {data = 0;ptr = new int(0);}// 拷贝构造函数(自定义)MyClass(const MyClass& other) {data = other.data;ptr = new int(*(other.ptr));}
};

使用拷贝构造函数可以创建对象的副本,确保新对象与原始对象具有相同的值。例如:

MyClass obj1;                  // 调用默认构造函数创建对象 obj1
obj1.data = 42;
*(obj1.ptr) = 100;MyClass obj2(obj1);            // 调用拷贝构造函数创建对象 obj2,复制 obj1 的值

默认拷贝构造函数和自定义拷贝构造函数:

  1. 默认拷贝构造函数:
    默认拷贝构造函数是由编译器自动生成的构造函数,当没有显式定义拷贝构造函数时,编译器会为类生成默认的拷贝构造函数。
    默认拷贝构造函数执行浅拷贝(shallow copy),即逐个成员变量地复制源对象的值到新对象中。
    对于指针成员变量,默认拷贝构造函数只会复制指针的值,而不会复制指针指向的数据。
class MyClass {
public:int data;int* ptr;// ...
};

如果没有自定义拷贝构造函数,编译器会为 MyClass 类生成一个默认的拷贝构造函数,执行浅拷贝。

  1. 自定义拷贝构造函数:
    自定义拷贝构造函数是用户根据类的需求自行定义的构造函数,用于根据自定义逻辑执行对象的复制操作。
    自定义拷贝构造函数可以根据需要接受同类型对象的引用或常量引用作为参数,以及其他必要的参数。
    自定义拷贝构造函数的实现可以执行 深拷贝(deep copy) 或其他自定义的复制逻辑。
class MyClass {
public:int data;int* ptr;// 自定义拷贝构造函数MyClass(const MyClass& other) {data = other.data;ptr = new int(*(other.ptr));}
};

在上述示例中,MyClass 类定义了一个自定义的拷贝构造函数。自定义拷贝构造函数根据需要接受同类型对象的常量引用作为参数,并执行深层复制,将源对象的值复制到新对象中。

移动构造函数:

C++ 移动构造函数(Move Constructor)是一种特殊的构造函数,用于将一个对象的资源所有权从一个对象转移到另一个对象,而无需执行深层复制操作。移动构造函数通常用于提高对象的性能和效率,特别是在处理大型对象或包含资源的对象时。

移动构造函数的特点如下:

  • 接受同类型对象的右值引用(&&)作为参数。
  • 用于创建新对象并从传递的右值引用对象中"窃取"资源。
  • 通常在移动语义中,移动构造函数会将传递对象的指针或资源的所有权转移到新对象,而不执行深层复制。
class MyClass {
public:int* data;// 默认构造函数MyClass() {data = new int(0);}// 移动构造函数MyClass(MyClass&& other) {data = other.data;other.data = nullptr;  // 将原对象的指针置为空,避免重复释放资源}
};

在上述示例中,MyClass 类定义了一个移动构造函数。移动构造函数接受一个同类型对象的右值引用 MyClass&& other 作为参数,并使用右值引用对象 other 中的资源来创建新对象。

在移动构造函数的实现中,将传递对象的指针 data 赋给新对象,然后将原对象的指针置为空,避免重复释放资源。

MyClass obj1;                  // 调用默认构造函数创建对象 obj1
obj1.data = new int(42);MyClass obj2(std::move(obj1));  // 调用移动构造函数创建对象 obj2,转移 obj1 的资源所有权

在上述示例中,通过使用 std::move() 将对象 obj1 转换为右值引用,并传递给移动构造函数,创建了一个新对象 obj2。这样,obj2 将获得 obj1 的资源所有权,而 obj1 中的指针被置为空。

类型转换构造函数

类型转换构造函数(Conversion Constructor)是一种特殊的构造函数,用于将一种类型的对象转换为另一种类型的对象。它允许在需要时隐式地进行类型转换,或者通过显式构造函数调用进行显式类型转换。

类型转换构造函数具有以下特点:

  • 它是一个构造函数,没有返回类型(包括 void)。
  • 它可以带有一个或多个参数,用于定义从当前类型到目标类型的转换方式。
  • 它可以定义隐式类型转换,这意味着在需要时编译器会自动调用类型转换构造函数,将一个对象转换为另一个类型。
  • 它也可以通过显式构造函数调用进行显式类型转换。
class MyInt {
public:int value;// 类型转换构造函数MyInt(double val) {value = static_cast<int>(val);}
};int main() {double num = 3.14;MyInt myNum = num;  // 隐式类型转换,调用类型转换构造函数MyInt myNum2 = MyInt(5.67);  // 显式类型转换,通过构造函数调用
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/760913.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Java版工程行业管理系统源码,提升工程项目的综合管理能力

工程项目管理涉及众多环节和角色&#xff0c;如何实现高效协同和信息共享是关键。本文将介绍一个采用先进技术框架的Java版工程项目管理系统&#xff0c;该系统支持前后端分离&#xff0c;功能全面&#xff0c;可满足不同角色的需求。从项目进度图表到施工地图&#xff0c;再到…

Java------数据结构之栈与队列(简单讲解)

本篇碎碎念&#xff1a;时隔n个月&#xff0c;继续写博客&#xff0c;假期落下的进度&#xff0c;在开学后努力追赶&#xff0c;假期不努力&#xff0c;开学徒伤悲啊&#xff0c;此时此刻真想对自己说一句&#xff0c;活该啊~~~~ 欠下的链表练习题讲解会在下次更新~~~~ 今日份励…

Day53| 1143 最长公共子序列 1035 不相交的线 53 最大子序和 动态规划

目录 1143 最长公共子序列 1035 不相交的线 53 最大子序和 动态规划 1143 最长公共子序列 class Solution { public:int longestCommonSubsequence(string text1, string text2) {vector<vector<int>> dp(text1.size() 1, vector<int>(text2.si…

Ubuntu20.04 安装fcitx5输入法

序 ubuntu 20.04.3下fcitx5 需要从flatpak安装&#xff0c;&#xff08;由于qt版本&#xff0c;fcitx5-config只能安装在20.10上&#xff09;&#xff0c;中间出了各种问题&#xff0c;最后发现以下解决方案最好&#xff1a; 安装flatpak (建议使用官方ppa,版本较新) 1 2 3 …

应届生/实习生租房经验帖

前言 作者&#xff1a;晓宜 个人简介&#xff1a;互联网大厂Java准入职&#xff0c;阿里云专家博主&#xff0c;csdn后端优质创作者&#xff0c;算法爱好者 博主本人在杭州互联网小镇和北京中关村都实习过一段时间&#xff0c;分享下租房的经历&#xff0c;以及在这过程中踩的坑…

视频素材库网站下载的地方在哪里?

视频素材库网站下载的地方在哪里&#xff1f;这是很多短视频创作者都会遇到的问题。别着急&#xff0c;今天我就来给大家介绍几个视频素材库网站下载的好去处&#xff0c;让你的视频创作更加轻松有趣&#xff01; 蛙学网&#xff1a;视频素材库网站下载的一定要选择蛙学网啦&am…

C++利用开散列哈希表封装unordered_set,unordered_map

C利用开散列哈希表封装unordered_set,unordered_map 一.前言1.开散列的哈希表完整代码 二.模板参数1.HashNode的改造2.封装unordered_set和unordered_map的第一步1.unordered_set2.unordered_map 3.HashTable 三.string的哈希函数的模板特化四.迭代器类1.operator运算符重载1.动…

WPF —— DataGrid数据网格

1 &#xff1a;DataGrid简介 DataGrid 是数据网格 : 可以显示网格数据的控件&#xff0c;通过自定义列模版 来去实现各种网格效果 &#xff0c; 可以使用以下几中标签显示不同数据 2 &#xff1a;DataGrid常用的组件 显示文本: DataGridTextColumn 显示复选框: DataGridChec…

【计算机考研】杭电 vs 浙工大 怎么选?

想求稳上岸的话&#xff0c;其他几所学校也可以考虑&#xff0c;以留在本地工作的角度考虑&#xff0c;这几所学校都能满足你的需求。 如果之后想谋求一份好工作&#xff0c;肯定优先杭电是比较稳的&#xff0c;当然复习的时候也得加把劲。 这个也可以酌情考虑&#xff0c;报…

C# 设置AutoScroll为true没效果的原因分析和解决办法

C#中添加tabControl 分页&#xff0c;将autoscroll设置为true发现缩小窗口没有滚动条效果。该问题出现后&#xff0c;检索发现也有很多人询问了该问题&#xff0c;但是都没有给出解决方案。 原因是内部button的属性Anchor设置为top、left、right、bottom导致的缩小界面窗口也没…

【逆向】常用指令操作adb和logcat

快将尘埃掸落 别将你眼眸弄脏 或许吧 谈笑中你早已淡忘 而我在颠沛中 已饱经一脸沧桑 思念需要时间 慢慢调养 &#x1f3b5; 张小九《余香》 在安卓开发和调试过程中&#xff0c;adb&#xff08;Android Debug Bridge&#xff09;是一个无可替代的工具。它…

为什么Hashtable不允许插入nuIl键和null值?

1、典型回答 浅层次的来回答这个问题的答案是&#xff0c;JDK 源码不支持 Hashtable 插入 value 值为 null&#xff0c;如以下 JDK 源码所示&#xff1a; 也就是 JDK 源码规定了&#xff0c;如果你给 Hashtable 插入 value 值为 null 就会抛出空指针异常。 并且看上面的 JDK …

node.js常用的命令

node.js常用的命令包括&#xff1a; 安装包。使用npm install <包名>版本号安装指定版本的包&#xff0c;或者使用npm install <包名>安装包到当前目录。 卸载包。使用npm uninstall <包名>卸载包。 全局安装包。使用npm install <包名> -g全局安装包…

MySQL面试高频简答题及答案解析

1. 请解释什么是关系型数据库?并列举关系型数据库的主要特点。 关系型数据库是采用关系模型来组织数据的数据库,其以行和列的形式存储数据,以便于用户理解。关系型数据库的主要特点包括易于编程、支持复杂查询以及支持事务处理等。 2. 简述MySQL的存储引擎及其作用。 MyS…

【Ubuntu】FTP站点搭建

配置顺序 前提条件&#xff1a;确保软件仓库可以正常使用&#xff0c;确保已正常配置IP地址 1.安装FTP服务 2.编辑FTP配置文件 3.设置开机自启 4.创建用户 5.配置用户限制名单 6.重启服务 7.查看运行状态 8.测试在同一局域网下的Windows查看文件 1.安装FTP服务 sudo apt insta…

网站建设中的HTTP 请求方法

快速入门 — Flask 0.10.1 文档 (jinkan.org) HTTP 请求方法 | 菜鸟教程 (runoob.com) HTTP &#xff08;与 Web 应用会话的协议&#xff09;有许多不同的访问 URL 方法。默认情况下&#xff0c;路由只回应 GET 请求&#xff0c;但是通过 route() 装饰器传递 methods 参数可以…

【STM32嵌入式系统设计与开发】——8usart(串口通讯实验)

这里写目录标题 一、任务描述二、任务实施1、ActiveBeep工程文件夹创建2、函数编辑&#xff08;1&#xff09;主函数编辑&#xff08;2&#xff09;USART1初始化函数(usart1_init())&#xff08;3&#xff09;USART数据发送函数&#xff08; USART1_Send_Data&#xff08;&…

Tempo Talents | 创新专业建设方案,赋能高校4+N大数据学科人才培养

数字经济成为国家战略&#xff0c;是新一轮的经济发展引擎&#xff0c;数字人才、复合型人才成为发展的关键和核心要素。各级政府、区域开始以区域产业为导向&#xff0c;培育、聚集产业所需的数智化人才。 高校作为人才培养的重要基地&#xff0c;也发挥着不可或缺的作用。他…

Linux系统之安装java开发环境

1 java简介 Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 面向对象程序设计语言和 Java 平台的总称。由 James Gosling和同事们共同研发&#xff0c;并在 1995 年正式推出&#xff0c;后来 Sun 公司被 Oracle &#xff08;甲骨文&#xff09;公司收购&#xff…

Linux进程控制(一)

一、fork函数 在linux中&#xff0c;父进程通过fork函数创建子进程&#xff0c;子进程返回0&#xff0c;父进程返回子进程的pid&#xff0c;出现错误返回-1。 当运行fork函数时&#xff0c;OS会为子进程创建task_struct、mm_struct&#xff08;进程地址空间&#xff09;、页表&…