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

网站建设都是模板欧米茄表官网

网站建设都是模板,欧米茄表官网,怎么制作网站视频播放器,电商专业网站建设的毕业设计C拷贝构造函数详解 什么是拷贝构造函数?拷贝构造函数的特征默认拷贝构造函数为什么需要显示定义构造函数?拷贝构造函数的调用场景什么时候不需要自己定义拷贝构造函数 什么是拷贝构造函数? 在现实生活中,拷贝构造函数就好像我们上…

C++拷贝构造函数详解

  • 什么是拷贝构造函数?
  • 拷贝构造函数的特征
  • 默认拷贝构造函数
  • 为什么需要显示定义构造函数?
  • 拷贝构造函数的调用场景
  • 什么时候不需要自己定义拷贝构造函数

什么是拷贝构造函数?

在现实生活中,拷贝构造函数就好像我们上学时候干的一件事——抄作业(doge,但在现实生活中,这是件不好的事,但是在类和对象中,拷贝构造函数确是一个作用极大的东西。

在创建对象时,能否船创建一个与已经存在对象一模一样的对象呢?当然可以,这时候就要使用拷贝构造函数了。

拷贝构造函数: 只有单个形参,该形参是对 本类类型对象的引用(一般常用const修饰),在用 已存在的类类型对象创建新对象时由编译器自动调用
对于内置类型,就相当于 int a = b,这样,用b来构造a
注意: 构造赋值是两件不一样的事,看下面一段代码:

//拷贝构造
int b = 10;
int a = b;//赋值
int a = 10, b;
b = a;

拷贝构造函数的特征

拷贝构造函数也是特殊的成员函数之一:

  1. 拷贝构造函数是构造函数的一个重载形式
  2. 拷贝构造函数的参数只有一个必须是类对象的引用,使用传值方法编译器会强制检查报错,因为会引发无穷递归问题。

相信这里大家一定会有疑惑,为什么传值的方法会引发无穷递归的问题?
看下面一段代码:

#include<iostream>
class Date 
{
private:int _year;int _month;int _day;
public:Date(int year = 1970, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){std::cout << "Date(const Date& d)" << std::endl;_year = d._year;_month = d._month;_day = d._day;}
}void func(Date d)
{}int main()
{Date d1(2023,5,1);func(d1);return 0;
}

上面这段代码的运行结果如下:
在这里插入图片描述

这说明了什么问题?
我们使用了拷贝构造函数,可是在哪里使用的呢?从代码上看,并没有看到我们使用了拷贝构造啊?

这里就涉及到一个经典的问题了,还记得形参和实参之间的关系吗?没错,就是她俩在搞鬼!!

  • 形参是实参的临时拷贝!!!
  • 形参是实参的临时拷贝!!!
  • 形参是实参的临时拷贝!!!
    重要的事情说三遍,没错!正是因为这个性质,在调用func函数时,我们将d1传给形参d,就发生了用d1来拷贝复制形参的出现,那么有了这一个理解,我们就能了解为什么在设计拷贝构造函数的时候不能使用传值调用了。

因为如果用传值调用,效率不高是一个,另外一个就是调用拷贝复制函数时,形参和实参之间的复制需要一直调用拷贝构造,就会出现无限递归的情况,具体看下图:

在这里插入图片描述

因此,现在的编译器为了避免这种无限递归的产生,会对复制构造函数传值的设计进行强制的检查,一旦我们用传值的方式设计拷贝构造函数,将无法完成编译。

默认拷贝构造函数

若未显示定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数对象对内置类型是按照字节方式直接拷贝的(这种拷贝又叫做浅拷贝,或者叫值拷贝),而对自定义类型是调用其拷贝构造函数来完成拷贝的。

在前面日期类的基础上,我们再创建一个类,来测试一下这个特性。

#include<iostream>
class Date 
{
private:int _year;int _month;int _day;
public:Date(int year = 1970, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){std::cout << "Date(const Date& d)" << std::endl;_year = d._year;_month = d._month;_day = d._day;}
};
class Time
{
private:int hour;int min;int second;Date x;
};int main()
{Time d1;Time d2(d1);return 0;
}

在这里插入图片描述

可以看到,我们并没有定义Time类的拷贝构造,所以使用的是系统自动生成的默认拷贝构造函数,而从运行结果看其确实符合上诉所说的特性。

为什么需要显示定义构造函数?

大家刚接触到拷贝构造函数的时候一定有一个问题,竟然编译器生成的拷贝构造函数已经可以完成字节序的值拷贝了,那还需要显示定义吗?也许对日期类这种比较简单的类不需要,那如果是更复杂的一些类呢?看下面的例子:

typedef int DataType; 
class Stack {
public:Stack(size_t capacity = 10) {_array = (DataType*)malloc(capacity * sizeof(DataType)); if (nullptr == _array) {perror("malloc申请空间失败"); return;}_size = 0;_capacity = capacity;}void Push(const DataType& data) {// CheckCapacity();_array[_size] = data; _size++;}~Stack(){if (_array){free(_array); _array = nullptr;_capacity = 0; _size = 0;}} 
private:DataType* _array;size_t _size;size_t _capacity;
};int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
}

上面这段代码在运行之后将会崩溃,为什么呢?我们首先来看看定义的两个stack对象里保存的东西:

在这里插入图片描述
两个对象动态申请的数组指向同一块空间,这就是默认拷贝构造函数带来的后果,而如此造成的结果并不是我们想要的,在程序结束调用析构的时候,将会对同一块空间释放两次,因此会造成错误。

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

拷贝构造函数的调用场景

  • 使用已存在对象创建新对象
  • 函数参数为类类型对象(形参的拷贝创建)
  • 函数返回值类型为类类型对象(创建临时变量

什么时候不需要自己定义拷贝构造函数

  1. 类成员都是自定义类型
  2. 所有的成员都只需要浅拷贝就能完成任务

好了,以上就是这篇博客的全部内容,如果大伙发现博主哪里写的有问题或者有疑惑的话,欢迎评论区指出!😘

http://www.yayakq.cn/news/675135/

相关文章:

  • 专门做推广的网站吗如何建设网站吸引人
  • 网站设计做哪些的简约wordpress
  • 网站外链资源模板网站建设 报价
  • 朝阳区规划网站wordpress输出文章id
  • win10系统可以做网站搭建网站建设空格怎么打
  • 网站跟网页的区别展厅展示公司
  • 电脑网站有哪些如何建设像艺龙一样网站
  • 建设网站前的目的高端网页设计培训
  • php网站后台模版视频门户网站建设项目标书
  • 类似于美团的网站开发网站首页的布局设计
  • wordpress网站同步插件企业crm软件
  • 手机网站和电脑网站跳转北京网站设计与网站制作
  • 沈阳工伤保险做实在哪个网站商标设计在线生成器
  • 网站设计公司要多少钱天津市建设 银行网站
  • 网站开发前端框架中国空间站结构示意图
  • 制作动态表情的网站dw网页制作作业
  • o2o网站建设基本流程图书馆网站建设费用
  • 在哪个网站可以做二建的题视频在线观看网站怎么建设
  • 坪山区住房和建设局网站怎么把自己的网站推广
  • asp做网站上传文件系统网站二维码收费怎么做
  • 建设网站赚钱的方法wordpress模版标签
  • 呼伦贝尔网站开发安卓aso优化排名
  • 济南高端网站设计策划沃尔玛网上商城app官方下载
  • 卫生监督 网站建设方案山东城市建设厅网站
  • 重庆专业网站推广报价php做网站视频播放下载功能
  • 商务网站建设与维护 ppt甘肃园区网络搭建
  • 河南网站建设公司|河南网站建设价格费用中小企业公司
  • 企业网站软件网站备案和域名备案
  • 网站建设精准精细快速盘州网站建设
  • 个人网站认证三方物流网站建设