c++ 拷贝构造函数_C++构造函数总结

2023-11-03

最近在找工作,比较忙,所以没有时间写文章了。找了一段时间了,还是没有什么收获。找工作给我一个最大的体会就是"基础要扎实,代码能力要强(这里的代码不是指那种业务逻辑的代码哦)"。

01 文章概要

这篇文章总结一下C++中的构造函数,然后自己实现一个MyString类,实现对MyString字符串的输入和输出。如果对C++熟悉的童鞋应该就能猜到后面要介绍的知识了:

  • C++的构造函数(分的细就是6种,粗一点就是4种)

介绍的过程中,不会对所有的都介绍的很细,不然就要花太多的时间啦。

02 C++中的构造函数分类

C++中的构造函数主要有下面几种:

  • 默认构造函数
  • 带参构造函数
  • 拷贝构造函数
  • 转换构造函数
  • 显式构造函数
  • 移动构造函数

其中转换构造函数、显式构造函数、拷贝构造函数、移动构造函数需要仔细讲一下。

什么是转换构造函数和显式构造函数?
看下面一段代码:

#include #include using namespace std;class Dog {public:Dog() {}Dog(const char* _name): name(_name) {}public:string name;};int main() {Dog dog = "Hei";cout << dog.name << endl;return 0;}

经过验证,这里代码是可以正常编译运行的,看一下16行: 你是不是很疑惑,为什么可以将一个常量字符串赋值为Dog类型的对象呢?

其实编译器自动做了隐式类型转换,调用了转换构造函数了,所以程序没有问题。所以转换构造函数的定义就出来了:只含有一个参数,并且该参数不是类的const引用成员,这个构造函数就是转换构造函数

但是,这样的写法太让人迷惑了,你也可以在构造函数前面加上explicit关键字,声明该构造函数不允许被隐式调用(第8行),然后上面的程序编译就会报错了。explitcit的用法如下:

  • explicit只能用于构造函数,禁止构造函数被隐式调用
  • explicit只有作用于单参构造函数才有作用,因为其它的构造函数都是显式调用的
  • 用explicit声明的构造函数称为显式构造函数

什么是拷贝构造函数和移动构造函数?

拷贝构造函数顾名思义就是在发生对象拷贝的时候调用的了,一般拷贝构造函数的写法如下(为什么我就不解释了,看不明白的需要补一下C++基础了):

 MyString(const MyString& str) {    cout << "The copy constructor is callback." << endl;        if(str.len == 0) {            return;        }        len = str.len;        data = new char[len+1];        memcpy(data, str.data, len);        data[len] = '0';    }

所以,拷贝构造函数在进行对象拷贝的时候采用的方式是"深拷贝",啥意思? 就是我申请一个新的内存空间,然后把你的内容全部拷贝在我自己的内容空间里面,然后你做了任何修改对我都没有影响,拷贝的很彻底。与深拷贝的对应还有浅拷贝,有兴趣的自己去查一下吧,这里就不多说了。

深拷贝有自己的优点,但是也有缺陷。如果我们在拷贝临时对象的时候,还是采用深拷贝的话,那么我就要: 申请内存、拷贝内容、释放临时对象。这样效率还是比较低的。

C++11为了解决临时对象的拷贝效率的问题,引入了右值引用和移动语义。

妈的,都是什么鬼? 如果要细讲的话,这一篇文章估计百分之八十的内容都是关于它的了,所以这一篇文章就不细讲了。只大概的介绍一下。

所谓的左值和右值,本质区别是能够取得它们的地址。但是我觉得你可以简单的理解一下:

  • 左值是表达式结束了之后仍然存在的持续化变量,比如a = 3; 表达式结束了,a仍然还存在。
  • 右值是表达式结束了之后就消失的临时变量,比如a = 1+2;1+2就是个临时变量。

有什么用呢? 先来看一下移动拷贝构造函数的写法:

MyString(MyString&& str) {    cout << "The move constructor is callback." << endl;        len = str.len;        data = str.data;        str.len = 0;        str.data = nullptr;    }

上面的移动拷贝构造函数仍然是拷贝str,但是没有做深拷贝,只是拷贝了str的data指针,然后将str.data置为空。相当于我把str的data的内容了过来。这样,就避免了内存空间的申请和拷贝的效率,效率自然就高了。

移动构造函数的参数是一个右值引用,因此在参数传入时要将左值转换为右值,使用std::move()来实现。

值得注意的是,移动语义改善了临时对象拷贝的效率,由于把临时对象内部的指针变量了过去,所以经移动拷贝之后,临时对象就失效了。

03 MyString类的代码实现

class MyString {public:    // 默认构造函数    MyString(): data(nullptr), len(0){     cout << "default constructor is callback." << endl;    }    // 带参构造函数    MyString(const char* _data) {        len = strlen(_data);    // strlen(_data)返回字符串_data的长度,不包含'0'        data = new char[len+1];        memcpy(data, _data, len);        data[len] = '0';    }    // 拷贝构造函数    MyString(const MyString& str) {    cout << "The copy constructor is callback." << endl;        if(str.len == 0) {            return;        }        len = str.len;        data = new char[len+1];        memcpy(data, str.data, len);        data[len] = '0';    }    // 拷贝赋值函数    MyString& operator=(const MyString& str) {    cout << "The copy = function is callback." << endl;        if(this == &str) {            return *this;        }        len = str.len;        data = new char[len+1];        memcpy(data, str.data, len);        data[len] = '0';        return *this;    }    // 移动构造函数    MyString(MyString&& str) {    cout << "The move constructor is callback." << endl;        len = str.len;        data = str.data;        str.len = 0;        str.data = nullptr;    }    // 移动赋值函数    MyString& operator=(MyString&& str) {    cout << "The move = function is callback." << endl;        if(this == &str) {            return *this;        }        len = str.len;        data = str.data;    // 浅拷贝,直接将内存移动过来        str.len = 0;        str.data = nullptr; // 移动拷贝之后,临时对象失效了        return *this;    }    // 析构函数    virtual ~MyString() {        len = 0;        if(data) {            delete[] data;            data = nullptr;        }    }    // 重载>>    friend istream& operator>>(istream& in, MyString& str) {        string tempstr;        getline(cin, tempstr, '');        str.len = tempstr.length();        str.data = new char[str.len+1];        memcpy(str.data, tempstr.c_str(), tempstr.length());        str.data[str.len] = '0';        return in;    }    // 重载<<    friend ostream& operator<> str1 >> str2 >> str3;MyString str_1_copy(str1);// 调用拷贝构造函数cout << "str_1_copy is: " << str_1_copy << endl;MyString str_2_copy(std::move(str2));// 调用移动拷贝构造函数cout << "str_2_copy is: " << str_2_copy << endl;MyString str4, str5;str4 = str1;// 调用赋值构造函数cout << "str4 is: " << str4 << endl;str5 = std::move(str3);cout << "str5 is: " << str5 << endl;// 调用移动赋值构造函数  return 0;}

运行结果分析如下:

c6bd2998a32b9435e455e05da8f36380.png

运行结果

04 小结

这篇文章主要还是介绍C++中的构造函数,对于C++11中引入的移动语义介绍的比较少,恰巧我个人觉得C++中的移动语义和完美转发这两个问题也是比较难以理解的概念,所以在这里先埋下一个伏笔,后面有时间了再专门用一到两篇文章介绍移动语义std::move()。

如果C++基础比较薄弱的童鞋不理解也没有关系,就当个玩笑看一下,先去补一下C++基础。移动语义这个概念,研究生期间做项目全是用的C++也没有遇到。

今天的内容就到这儿了。如果对我的推|文有兴趣,欢迎转、载分、享。也可以推荐给朋友关、注哦。只推干货,宁缺毋滥。

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

c++ 拷贝构造函数_C++构造函数总结 的相关文章

  • 自动化遍历-appcrawler

    下载appclawler 下载地址 https pan baidu com s 1dE0JDCH list path 2F 查看帮助文档 java jar appcrawler 2 4 0 jar with dependencies jar
  • JS-ES6类

    使用js的class需注意以下几点 1 通过class关键字创建类 类名我们还是习惯性定义首字母大写 2 类里面有个constructor函数 可以接受传递过来的参数 同时返回实例对象 3 constructor 函数只要new生成实例时
  • seq2seq

    我的书 淘宝购买链接 当当购买链接 京东购买链接 seq2seq是通用编码器 解码器框架 encoder decoder framework 可以用在机器翻译 文本摘要 会话建模 图像描述 源码 https github com googl
  • 【编译原理】flex实现词法分析器

    flex自动实现词法分析器 FLEX 与 BISON 的使用 FLEX介绍 Flex是一个生成词法分析器的工具 它可以利用正则表达式来生成匹配相应字符串的C语言代码 其语法格式基本同Lex相同 单词的描述称为模式 Lexical Patte
  • 项目中好用的方法

    1 过滤 数组子项是对象的 对象有重复的 let arr res data filter function item index self return self findIndex el gt el applyPerson item ap
  • jsp 不能识别 el 表达式 的解决方法

    在以前使用EL表达式的时候 在JSP页面直接使用就可以了 但昨天我在做项目的时候在JSP页面上的EL表达式不能被识别 如 loginForm username 在页面上还是显示 loginForm username 后来我在JSP头上加上红
  • java面向对象----封装 && 构造器

    目录 封装和隐藏 为什么需要封装 信息的封装和隐藏 四种访问权限修饰符 构造器 构造方法 构造器的特征 语法格式 构造器重载 构造器重载举例 属性赋值过程 JavaBean UML类图 关键字 this this是什么 使用this 调用属
  • 抠图算法Background Matting:The world is your green screen

    论文地址 https arxiv org abs 2004 00626 代码 https github com senguptaumd Background Matting 背景介绍 抠图是照片编辑和视觉效果中使用的标准技术 在现有的抠图算
  • Python之浮点型

    python默认的是17位小数的精度 不支持32bit的单精度浮点数 如果程序需要精确控制区间和数字精度 可以考虑使用numpy扩展库 一 单精度和双精度的区别 内存不同 单精度浮点数占用4个字节 32位 存储空间 符号位1位 阶码8位 位
  • 【MySQL安装过程中显示ddl文件缺失】

    写在前面 每个人都遇到过 无法找到 dll文件 的消息弹窗 各位 这个问题终于可以解决了 在这里你可以找到电脑上最常丢失或损坏的文件 自由下载 无任何费用 1 问题描述 安装MySQL过程中遇到的问题 如图 这些是同一类问题 都是由于缺少
  • Go导入本地包

    举例来说项目文件结构如 C go mod go sum main go models User go 如果想要再main go中导入models包 那么首先需要在go mod中配置 则可以用 这种方式来导入models中的文件
  • 【读书笔记】周志华 机器学习 第五章 神经网络

    第五章 神经网络 1 神经元模型 2 感知机和多层网络 3 误差反向传播算法 4 局部极值点和鞍点 5 其他神经网络 6 参考文献 1 神经元模型 在生物神经网络中 一个神经元A与其他神经元相连 当它兴奋时 会向相连的神经元B发送化学物质改
  • CTFHUB-Refer注入

    Referer Referer 指当前请求的URL是在什么地址引用的 例如在www a com index html页面中点击一个指向www b com的超链接 那么 这个www b com的请求中的Referer就是www a com i
  • 区块链入门笔记(一)区块链概括

    区块链入门 李永乐老师的两个视频可以快速帮助入门区块链 1 比特币和区块链啥原理 矿机挖矿咋回事 2 比特币交易如何防伪 私钥公钥地址啥意思 比特币发展历史 在2008年之前 主要研究是比特币的基础例如数据加密 分布式系统等等 1 中本聪在
  • Valve.VR.SteamVR_AutoEnableVR_UnityPackage.Update () (at Assets/SteamVR/Editor/SteamVR_AutoEnableVR_

    unity 中导入 Steam Vr puls 报错 Valve VR SteamVR AutoEnableVR UnityPackage Update at Assets SteamVR Editor SteamVR AutoEnable
  • 适配ios13

    更新Xcode之后 新项目需求 新建项目发现多了如图1所示两个新的文件SceneDelegate h和SceneDelegate m 运行之后发现黑屏 无论是真机还是模拟器都不行 换到iOS12的手机上则可以正常运行 查看官方文档 Scen
  • Charge IC logic Q&A

    Q Q4 关断有哪些影响 A 1 充电停止 2 Vbat 到 Vsys 通路被断开 Vbus 到 Vsys 通路不受影响 Q Q4 可能被打开的情况 A 1 手机时 shipmode 模式时插入充电器 2 清除 BATFET DIS 标志位
  • pytorch查看网络模型变量以及对应的尺寸

    今天看代码发现 自己对于网络中需要更新的参数并不是很熟悉 然后百度发现了这个方法 记录一下 在自己定义的模型下面加入这一行就可以查看了 for name param in model named parameters print name
  • 【JAVA面试题】为什么会出现4.0-3.6=0.40000001这种现象?

    这种舍入误差的主要原因是 浮点数值采用二进制系统表示 而在二进制系统中无法精确地表示分数 1 10 这 就好像十进制无法精确地表示分数 1 3 样 如果在数值计算中不允许有任何舍入误差 就应该使用 BigDecimal类 浮点数值不适用于无

随机推荐

  • mysql drop语句怎么用_SQL DROP 语句

    http www cnblogs com troywithblog archive 2013 05 24 3096515 html 通过使用 DROP 语句 可以轻松地删除索引 表和数据库 SQL DROP INDEX 语句 我们可以使用
  • sql delete删除的数据怎么恢复_如何恢复按下Shift + DELETE键永久删除的文件和资料夹?...

    简单删除和Shift Delete永久删除 想删除电脑上的任何文件 有以下两种方式 按 DELETE 键简单删除文件 在这种模式下 文件被移动到回收站 此时 如果我们想要恢复已删除的文件和资料夹 请打开回收站 在文件上按右键选择 还原 按
  • Proxmox VE ZFS 开启Thin Provision(精简配置)

    前言 最近在为一台PVE 的VM添加大容量磁盘时 20T 遇到out of disk 错误 遂发现 ZFS在没有开启Thin Provision前 会提前分配磁盘空间 即使一个字节也没有写入 在开启Thin Provision 后问题得到解
  • 【Unity插件】最多的插件合集

    一 前言 最近整理了一下文章 发现我分享了很多的插件 但是如果要查找某一款插件 还需要去搜索才能找到 很不方面 就想要将写过的所有的插件分享也好 教程也好 做一个汇总 然后这篇文章还会不断的更新 在有新的插件之后 熟悉我的人都知道 我对插件
  • python 逆向

    1 目标网址 https www qimingpian com finosda project pinvestment 2 抓包查看响应体 3 数据加密 4 打上断电进行调试 5 抠出代码进行运行 6 总结 function o t 就是我
  • shell sed过滤器详解

    1 Sed简介sed 是一种在线编辑器 它一次处理一行内容 处理时 把当前处理的行存储在临时缓冲区中 称为 模式空间 pattern space 接着用sed命令处理缓冲区中的内容 处理完成后 把缓冲区的内容送往屏幕 接着处理下一行 这样不
  • 怎么维护自己的电脑

    文章目录 我的电脑 日常维护措施 维护技巧 键盘 屏幕清洁 清理磁盘空间 控制温度 电脑换电池 无论是学习还是工作 电脑都是IT人必不可少的重要武器 一台好电脑除了自身配置要经得起考验 后期主人对它的维护也是决定它寿命的重要因素 你日常是怎
  • 开讲啦!0基础也能玩转飞桨开源社区

    作为cs ai学生 你是否经历过这些至暗时刻 希望快速入门深度学习 无奈网上到处都是看不懂 黑话 一遍遍计算综测小数点后四位 不断在保研边缘反复横跳 看着 洁白如新 的履历叹气 一听到 考研复试 就头皮发麻 0实习 的标签在求职时毫无竞争力
  • 主变压器新装或大修后投入运行为什么有时气体继电器会频繁动作?遇到此类问题怎样判断和处理?

    主变压器新装或大修后投入运行为什么有时气体继电器会频繁动作 遇到此类问题怎样判断和处理 答 新装或大修的变压器在加油 滤油时 会将空气带入变压器内部 若没有能够及时排出 则当变压器运行后油温会逐渐上升 形成油的对流 将内部贮有的空气逐渐排除
  • 个人信息可携带权的中国路径(线上)研讨会

    个人信息保护法 将于今年11月1日正式实施 其中首次提出了个人信息可携带权的相关法条 体现了将个人信息权利还于个人的立法思路 也为进一步释放数据要素生产力带来了新的历史机遇 为深入了解个人信息可携带权在全球范围的发展及在中国的可行落地路径
  • lstm(三) 模型压缩lstmp

    lstmp结构 对于传统的lstm而言 i t W i
  • Linux专栏(二):创建虚拟机与Ubuntu安装

    文章目录 1 下载Ubuntu20 04镜像 2 创建虚拟机 3 安装Ubuntu系统 本文将介绍在VMware中如何创建虚拟机并安装Ubuntu20 04系统 1 下载Ubuntu20 04镜像 下载地址 Ubuntu官网镜像下载 2 创
  • 复旦NLP团队发布80页大模型Agent综述,一文纵览AI智能体的现状与未来

    来源 机器之心 智能体会成为打开 AGI 之门的钥匙吗 复旦 NLP 团队全面探讨 LLM based Agents 近期 复旦大学自然语言处理团队 FudanNLP 推出 LLM based Agents 综述论文 全文长达 86 页 共
  • block(块),page(页),buffer cache(块缓冲)区别与联系

    在自己的理解里 块就是用来管理磁盘空间的 就像我们在给一个磁盘建立文件系统时候 我们可以指定block size 而页是针对内存管理 例如从磁盘读出的数据就缓存在内存页中 但突然对关buffer cache block buffer 这些东
  • vue项目实现搜索功能

    使用vue框架实现以下要求 1 点击 首页 顶部搜索框 通过路由跳转到搜索页 并实现关键字模糊搜索功能 2 搜索页和首页下面用到的JSON数据自行模拟 并正确搜索渲染出来 3 在搜索页保留每次的搜索历史关键字 在搜索页的 历史搜索 中显示出
  • 微信小程序wx.request 使用 post方式传参

    参考网址 https blog csdn net lengxin337 article details 78234503 重点注意 method 是 get 方式的时候 header为 Content Type application js
  • 产品不快,你就死定了!

    作者碎碎念 创业团队做产品要拼迭代速度 天下武功 唯快不破 扎克伯格说 不酷 你就死定了 我要套用他的话说 不快 你就死定了 因为太阳底下没有新鲜事 聪明人辣么多 凭空想出一个绝世好点子 你没戏的 但是 发现别人做得不足的地方 再迅速赶超
  • java.net.SocketException:Connection reset

    背景 HttpClient远程调用HTTPS的API时 报错java net SocketException Connection reset 原因 Jdk版本差异导致的异常 由于Jdk1 7默认的是TLS的协议版本是v1 0 而Jdk1
  • C++工厂模式总结-简易版反射

    设计模式之factory method与c 反射 记我曾经的误解 Factory Method的官方解释是 Define an interface for creating an object but let subclasses deci
  • c++ 拷贝构造函数_C++构造函数总结

    最近在找工作 比较忙 所以没有时间写文章了 找了一段时间了 还是没有什么收获 找工作给我一个最大的体会就是 基础要扎实 代码能力要强 这里的代码不是指那种业务逻辑的代码哦 01 文章概要 这篇文章总结一下C 中的构造函数 然后自己实现一个M