C++ —— 拷贝构造函数

C++ —— 拷贝构造函数

  • 引言
  • 编译器给的拷贝构造函数
  • 默认拷贝构造函数
  • 调用拷贝构造函数的情况

引言

用四种方式创建对象的示例代码如下:

#include <iostream>
using namespace std;class Car
{
public:string c_brand;float c_acceleration;Car() {c_brand.clear(); c_acceleration = 0.0; cout << "普通 Car constructor" << endl;}~Car() {cout << "普通 Car destructor" << endl;}void show() {cout << "品牌: " << c_brand << ", 加速度: " << c_acceleration << endl;}};int main() {Car c1;Car c2 = Car();Car* c3 = new Car;Car* c4 = new Car();delete c3;delete c4;return 0;
}

以上程序运行时会调用四次构造函数和析构函数。

编译器给的拷贝构造函数

用一个已存在的对象创建新的对象,不会调用(普通)构造函数,而是调用拷贝构造函数。如果类中没有定义拷贝构造函数,编译器将提供一个拷贝构造函数,它的功能是把已存在对象的成员变量赋值给新对象的成员变量。
用一个已存在的对象创建新的对象的语法:
类名 新对象名 (已存在的对象名);
类名 新对象名 = 已存在的对象名;
示例代码如下:

int main() {Car c1;c1.c_brand = "Tesla"; c1.c_acceleration = 100;Car c2 (c1); // 用已存在的对象c1创建新对象c2# Car c2 = c1; // 效果是一样的c2.show();return 0;
}

运行效果如下:

普通 Car constructor
品牌: Tesla, 加速度: 100
普通 Car destructor
普通 Car destructor

第一行日志是创建c1的时候显示出来的,创建c2时,没有日志显示,说明没有调用普通构造函数。最后,c1c2销毁的时候,都调用了析构函数。
对于目前的Car类,没有定义拷贝构造函数,但是编译器给了一个拷贝构造函数,它的功能是把c1的成员变量赋值给c2的成员变量。

默认拷贝构造函数

拷贝构造函数的语法:
类名 (const 类名& 对象名) {......}
对现有Car类增加拷贝构造函数,代码如下:

#include <iostream>
using namespace std;class Car
{
public:string c_brand;float c_acceleration;Car() {c_brand.clear();c_acceleration = 0.0;cout << "普通 Car constructor" << endl;}// 默认拷贝构造函数Car(const Car &cc) {c_brand = "拷贝的" + cc.c_brand;c_acceleration = 100000 + cc.c_acceleration;cout << "拷贝 Car constructor" << endl;}~Car() {cout << "普通 Car destructor" << endl;}void show() {cout << "品牌: " << c_brand << ", 加速度: " << c_acceleration << endl;}
};int main() {Car c1;c1.c_brand = "Tesla"; c1.c_acceleration = 100;Car c2 (c1);c2.show();return 0;
}

运行结果如下:

普通 Car constructor
拷贝 Car constructor
品牌: 拷贝的Tesla, 加速度: 100100
普通 Car destructor
普通 Car destructor

拷贝构造函数的注意事项:

  • 访问权限必须是public
  • 函数名必须与类名相同
  • 没有返回值,不写void
  • 如果类中定义了拷贝构造函数,编译器将不提供默认的拷贝构造函数;
  • 拷贝构造函数可以重载,可以有默认参数;但是,重载的时候,形参中一定要有类本身常引用

带参数拷贝构造函数示例代码如下:

Car(const Car &cc, int n) {c_brand = "带参数的拷贝构造函数" + cc.c_brand;c_acceleration = cc.c_acceleration * n;cout << "带参数的拷贝构造函数 Car constructor" << endl;
}

调用带参数拷贝构造函数main()函数示例代码如下:

int main() {Car c1;c1.c_brand = "Benz";c1.c_acceleration = 111;Car c2(c1, 9);c2.show();return 0;
}

运行效果如下:

普通 Car constructor
带参数的拷贝构造函数 Car constructor
品牌: 带参数的拷贝构造函数Benz, 加速度: 999
普通 Car destructor
普通 Car destructor

  • 如果类中重载拷贝构造函数没有定义默认的拷贝构造函数编译器也会提供默认的拷贝构造函数。

调用拷贝构造函数的情况

  1. 已经存在的对象创建新对象的时候,会调用拷贝构造函数;
  2. 值传递的方式调用函数时,如果实参对象,会调用拷贝构造函数
void func(Car c) {c.show();
}int main() {Car c1;c1.c_brand = "BMW"; c1.c_acceleration = 4;func(c1);return 0;
}

Car类的定义不变,增加函数void func(Car c) {...},并在main函数中调用。运行结果如下:

普通 Car constructor
拷贝 Car constructor
品牌: 拷贝的BMW, 加速度: 100004
普通 Car destructor
普通 Car destructor

  1. 函数以的方式返回对象时,可能会调用拷贝构造函数(VS会调用,Linux不会,g++编译器做了优化)。代码如下:
Car func() {Car c;c.c_brand = "Ferrari";c.c_acceleration = 66;cout << "func c地址:" << &c << endl;return c;
}int main() {Car c1 = func();c1.show();cout << "main c1地址:" << &c1 << endl;return 0;
}

运行结果如下:

普通 Car constructor
func c地址:0x7ffe469b4c50
品牌: Ferrari, 加速度: 66
main c1地址:0x7ffe469b4c50
普通 Car destructor

可以看到,此时并没有调用拷贝构造函数(我使用的是Linux系统)。这是因为,编译器认为没必要创建对象,可以不销毁func()函数中创建的那个对象c

感谢浏览,一起学习!

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

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

相关文章

centos 8 中安装Docker

注&#xff1a;本次样式安装使用的是centos8 操作系统。 1、镜像下载 具体的镜像下载地址各位可以去官网下载&#xff0c;选择适合你们的下载即可&#xff01; 1、CentOS官方下载地址&#xff1a;https://vault.centos.org/ 2、阿里云开源镜像站下载&#xff1a;centos安装包…

关于Profinet 从站转 EtherNet/IP 从站网关详细说明

一、产品概述 1.1 产品用途 本产品是 PN(Profinet) 和 EtherNet/IP 网关&#xff0c;使用数据映射方式工作。 本产品在 PN 侧作为 PN IO 从站&#xff0c;接 PN 主站设备&#xff0c;比如西门子 PLC 等&#xff1b;在EtherNet/IP 侧做为 EtherNet/IP 从站&…

【SH】Xiaomi9刷Windows10系统研发记录 、手机刷Windows系统教程、小米9重装win10系统

文章目录 参考资料云盘资料软硬件环境手机解锁刷机驱动绑定账号和设备解锁手机 Mindows工具箱安装工具箱和修复下载下载安卓和woa资源包第三方Recovery 一键安装Windows准备工作创建分区安装系统 效果展示Windows和Android一键互换Win切换安卓安卓切换Win 删除分区 参考资料 解…

企业服务-团队协作相关平台极简介绍

前言 最近&#xff0c;为一家企业做咨询&#xff0c;该公司主要从事地产行业&#xff0c;老板李总招了几名研发人员&#xff0c;想着开发自己的行业APP&#xff0c;但是3年了&#xff0c;产品一直拿不出手&#xff0c;按李总的说法&#xff0c;产品还是很不成熟&#xff0c;但…

怎么防止SQL注入攻击

引言 SQL注入攻击是黑客对数据库进行攻击的常用手段之一&#xff0c;随着B/S模式应用开发的发展&#xff0c;使用这种模式编写应用程序的程序员也越来越多。但是由于程序员的水平及经验参差不齐&#xff0c;相当大一部分程序员在编写代码的时候&#xff0c;没有对用户输入数据…

一文说清楚Linux gdb

以下是关于 GDB&#xff08;GNU Debugger&#xff09; 的详细介绍&#xff1a; 什么是 GDB&#xff1f; 定义 GDB&#xff08;GNU Debugger&#xff09;是 GNU 项目开发的一款功能强大的调试工具&#xff0c;用于调试 C、C、Fortran 等语言编写的程序。它允许开发者执行程序时…

api开发及运用小红书笔记详情api如何获取笔记详情信息

item_get_video-获得某书笔记详情 smallredbook.item_get_video 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,i…

蓝桥杯第二天学习笔记

二维码生成&#xff1a; import qrcode from PIL import Image, ImageDraw, ImageFont import osdef generate_custom_qr_code(data, qr_file_path, logo_file_pathNone, textNone):# 创建QRCode对象qr qrcode.QRCode(version1,error_correctionqrcode.constants.ERROR_CORRE…

Springboot和Es整合

说明&#xff1a;本文章主要是简单整合和简单增删改查。 1.pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…

stack_queue的底层,模拟实现,deque和priority_queue详解

文章目录 适配器Stack的模拟实现Queue的模拟实现vector和list的对比dequedeque的框架deque的底层 priority_queuepriority_queue的使用priority_queue的底层仿函数的使用仿函数的作用priority_queue模拟实现 适配器 适配器是一种模式&#xff0c;这种模式将类的接口转化为用户希…

基于Python机器学习、深度学习技术提升气象、海洋、水文领域实践应用-以ENSO预测为例讲解

1. 背景与目标 ENSO&#xff08;El Nio-Southern Oscillation&#xff09;是全球气候系统中最显著的年际变率现象之一&#xff0c;对全球气候、农业、渔业等有着深远的影响。准确预测ENSO事件的发生和发展对于减灾防灾具有重要意义。近年来&#xff0c;深度学习技术在气象领域…

网络安全概述

在早期的互联网&#xff08;也是一种计算机网络&#xff09;中数据都是明文传输的&#xff0c;例如直接使用http协议。但由于越来越多的商业和政府的数据也都在互联网传输&#xff0c;直接使用明文传输&#xff0c;相当于让数据在网络中裸奔&#xff0c;而且网络中攻击者可以直…

39.【4】CTFHUB web sql 布尔注入

进入靶场 按照提示输入1 布尔注入只显示正确与否&#xff0c;手动注入太麻烦,用sqlmap -dbs爆出库名 -tables爆出表名 -columns 爆出字段名 --dump得到flag 笔记 1&#xff0c;sqlmap使用步骤 -dbs 爆出表名 -tables爆出库名 -columns爆出字段名 --dump爆出字段内容 2&a…

C#中通道(Channels)的应用之(生产者-消费者模式)

一.生产者-消费者模式概述 生产者-消费者模式是一种经典的设计模式&#xff0c;它将数据的生成&#xff08;生产者&#xff09;和处理&#xff08;消费者&#xff09;分离到不同的模块或线程中。这种模式的核心在于一个共享的缓冲区&#xff0c;生产者将数据放入缓冲区&#x…

【STM32】HAL库USB实现软件升级DFU的功能操作及配置

【STM32】HAL库USB实现软件升级DFU的功能操作及配置 文章目录 DFUHAL库的DFU配置修改代码添加条件判断和跳转代码段DFU烧录附录&#xff1a;Cortex-M架构的SysTick系统定时器精准延时和MCU位带操作SysTick系统定时器精准延时延时函数阻塞延时非阻塞延时 位带操作位带代码位带宏…

kotlin的dagger hilt依赖注入

依赖注入&#xff08;dependency injection, di&#xff09;是设计模式的一种&#xff0c;它的实际作用是给对象赋予实例变量。 基础认识 class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceSta…

Uniapp判断设备是安卓还是 iOS,并调用不同的方法

在 UniApp 中&#xff0c;可以通过 uni.getSystemInfoSync() 方法来获取设备信息&#xff0c;然后根据系统类型判断当前设备是安卓还是 iOS&#xff0c;并调用不同的方法。 示例代码 export default {onLoad() {this.checkPlatform();},methods: {checkPlatform() {// 获取系…

【MySQL】MVCC详解, 图文并茂简单易懂

欢迎来到啊妮莫的学习小屋 祝读本文的朋友都天天开心呀 目录 MVCC简介快照读与当前读快照读当前读 隔离级别隐藏字段和Undo Log版本链✨MVCC原理--ReadView✨ReadView简介设计思路适用隔离级别重要内容 ReadView规则MVCC整体流程 不同隔离级别下的MVCC读已提交可重复读 总结 M…

VSCode Live Server 插件安装和使用

VSCode Live Server是一个由Ritwick Dey开发的Visual Studio Code扩展插件&#xff0c;它提供了一个带有实时重载功能的本地开发服务器。在VSCode中安装和使用Live Server插件进行实时预览和调试Web应用程序。这将大大提高前端开发效率&#xff0c;使网页设计和开发变得更为流畅…

MC1.12.2 macOS高清修复OptiFine运行崩溃

最近在玩RLCraft&#xff0c;在windows中运行正常的&#xff0c;移植到macOS中发现如果加载OptiFine模组就会崩溃 报错日志 报错日志如下&#xff0c;其中已经包含了各种版本信息&#xff0c;我就不单独说明了。这里说一下&#xff0c;报错的时候用的是oracle jdk x64的&…