深入理解c++构造函数, 复制构造函数和赋值函数重载(operator=)

以下代码编译及运行环境均为 Xcode 6.4, LLVM 6.1 with GNU++11 support, Mac OS X 10.10.2

调用时机

看例子

1,2,3,4 是我们创建一个变量的最主要的方法(构造序列本文不讨论), 其中1,2,3是变量定义, 4是赋值. 因此很明显:

const来捣乱

那么const又起到什么作用了呢?

继续来看例子

上述代码都会编译出错, 原因是 “No matching constructor”. 看代码不难发现原因, creator函数返回的是Base类型, 在c++11里面, 这个称为右值(rvalue), 但是我们的复制构造函数和赋值函数的参数类型都是非const引用类型, 而右值是不允许做这种类型参数的, 所以就编译出错了. 解决方案有两个:

如下所示

其中, const引用类型是最通用的作法, 它可以兼容左值和右值, 也兼容古老的编译器, 右值类型则是c++11引进的新特性(使用&&表明), 可以针对左值和右值选择不同的实现, 比如使用std::move替代operator=, 从而减少内存的申请. 因此, 如果没有特殊需要, 使用const引用类型作为复制构造函数与赋值函数的参数类型.

至此, 构造函数的坑基本说完了, 因为不牵扯到返回值和函数类型的问题, 但是赋值函数(operator=)还有更多的坑来理一理.

const继续搅局

在一个类的成员函数中, const可以出现三个地方: 返回值, 参数, 函数.

因此一个函数可以有8个变种, 但是c++不允许参数类型相同,返回值类型不同的重载, 因此一个函数最多有4种实现.

我们先考虑返回const类型的情况

输出结果

结果很明显, 被赋值变量决定函数, 赋值变量决定参数, a=b 等价于 a.operator(b), 这里没什么问题.

但是, 有一个很奇怪的地方, a=d 这一句, a是非const的, 调用了 const A& operator=(const A& a) [const d > a], 返回值是个const类型, 这怎么可以呢? 返回值的const是什么意思呢? 这是非常有迷惑性的. 这个问题的关键点在于:

a是这个函数的一部分, 并不是返回值的承接者. 因此 a=d 实际上是等价于 const A& ret = a.operator=(d), 也就是说, operator=的返回值类型和被赋值的变量是没有任何关系的!

加入以下代码

2会编译错误, 原因就在于把 const A& 绑定给 A&, 这肯定是错误的. 因此再重复一遍, operator=的返回值和被赋值变量没有任何关系.

那么返回值有什么意义呢? 这就和iostream类似了, 是为了进行串联赋值, 亦即 a=b=c

来看最后的例子

可以得出如下结论:

Original: https://www.cnblogs.com/dabaopku/p/4849377.html
Author: 大宝pku
Title: 深入理解c++构造函数, 复制构造函数和赋值函数重载(operator=)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/536497/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • C++矩阵运算库推荐

    最近在几个地方都看到有人问C++下用什么矩阵运算库比较好,顺便做了个调查,做一些相关的推荐吧。主要针对稠密矩阵,有时间会再写一个稀疏矩阵的推荐。 Armadillo:C++下的Ma…

    C++ 2023年5月29日
    061
  • EclipseC++学习笔记-7 汉化

    1、复制https://download.eclipse.org/technology/babel/update-site/latest/ 注意要和版本保持一致,如果版本不对安装之…

    C++ 2023年5月29日
    057
  • C++案例——协助破案

    协助破案。假设已经查清,有 A、B、C、D、E 五个嫌疑人可能参与制造了一起抢劫银行案,但不知道其中哪几个是真正的案犯。不过,有确凿证据表明: 上述论断可以用数理逻辑中的正规表达式…

    C++ 2023年5月29日
    039
  • C++11 列表初始化

    在我们实际编程中,我们经常会碰到变量初始化的问题,对于不同的变量初始化的手段多种多样,比如说对于一个数组我们可以使用 int arr[] = {1,2,3}的方式初始化,又比如对于…

    C++ 2023年5月29日
    043
  • EclipseC++学习笔记-10 warnings being treated as errors,,error: format ‘%u’ expects argument of type

    增加选项All Options增加-Wformat=0 本博客是个人工作中记录,遇到问题可以互相探讨,没有遇到的问题可能没有时间去特意研究,勿扰。另外建了几个QQ技术群:2、全栈技…

    C++ 2023年5月29日
    039
  • C++类中静态数据成员MAP如何初始化

    cpp;gutter:true; conv_xxx.hpp</p> <p>class convolution { …</p> <pre…

    C++ 2023年5月29日
    052
  • C+++string类如何判断字符串为空

    string类是C++STL类之一,有很丰富的接口。 string类为空,实际也就是元素为0个。 可以按照如下方式判断: 1、string类有自己的成员函数empty, 可以用来判…

    C++ 2023年5月29日
    061
  • C++ 模板类相关问题

    1.模板类中的函数定义与实现必须全部写在头文件中 C++中每一个对象所占用的空间大小,是在编译的时候就确定的,在模板类没有真正的被使用之前,编译器是无法知道,模板类中使用模板类型的…

    C++ 2023年5月29日
    045
  • Google C++ 单元测试 GTest

    from : http://www.cnblogs.com/jycboy/p/6057677.html 一、设置一个新的测试项目 在用google test写测试项目之前,需要先编…

    C++ 2023年5月29日
    032
  • EclipseC++学习笔记-4 使用win11 wslg 启动应用

    wslg在win10下无法安装,升级win11后才可以基本按网上方法都能安装成功,但需要注意两点1、wsl –update2、如果启动程序不报错,但是不显示窗口的话 e…

    C++ 2023年5月29日
    038
  • 347. 前 K 个高频元素 (优先队列 c++)

    【C++】优先队列的预备知识 对于我这种初学者来说,一个优先队列就给我搞蒙了,在此记录一下,造福后来人 定义 priority_queue<type, container, …

    C++ 2023年5月29日
    049
  • Dijkstra算法(二)之 C++详解

    迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。 基本…

    C++ 2023年5月29日
    043
  • EclipseC++学习笔记-8 兼容vim

    1、搜索vim2、点击install 本博客是个人工作中记录,遇到问题可以互相探讨,没有遇到的问题可能没有时间去特意研究,勿扰。另外建了几个QQ技术群:2、全栈技术群:616945…

    C++ 2023年5月29日
    044
  • c++ 读写文本文件

    1 #include 2 #include // 读写文件的头文件 …

    C++ 2023年5月29日
    039
  • C++的sort函数

    参考: https://baike.baidu.com/item/sort%E5%87%BD%E6%95%B0/11042699?fr=aladdin https://blog.c…

    C++ 2023年5月29日
    054
  • C++ *和&

    概述 在c++中,当申明变量int *p 的时,表示p是一个储存地址的变量;比如int _p=0,表示p指向地址为00000000的地址单元。当申明指针p之后,再用_p表示p指向的…

    C++ 2023年5月29日
    051
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球