C++拷贝构造函数---理解(配图文代码)

news2024/11/19 21:19:22

序:

        说实话,博主卡了一天,哎,老了。。。。理解能力不行。有时候还想着先跳过把,结果下班后,还在纠结是不是自己打开的方式不对,这不,刚理解了点,回来写下笔记,因为初学c++,所以说的可能没那么准确,不对的地方,请多包涵,也是只是想说怕哪天忘记了回头来看下笔记估计能想起来。

        看完博文,博主希望你能理解下几个点

        1、拷贝构造函数是什么玩意。

        2、非得用他吗,解决啥痛点。

        3、怎么写!

正文

        先跟着博主思路来吧,说道哪,理解到哪。

        1、首先,一下是一个类Cyc,主要实现 打印a,b的操作

#include <iostream>
// #include <windows.h>
using namespace std;
// #include "head.h"
class Cyc{
    int a,b;
    public:
        Cyc(int x,int y){
            a=x;b=y;
        };
        void getAB(){
            cout<<"a="<<a<<",b="<<b;
        };
};
// 程序的主函数
int main()
{
   Cyc c(1,2);
   c.getAB();
   return 0;
}

         2、我们现在main里 要在定义一个Cyc类的对象e,传参也是1,2 ,你干啥要弄两个传参一模一样的Cyc的对象?

        举个例子,小明120斤,吃完了3个苹果后126;请问多了几斤?之前的c对象就是小明之前的体重,现在新建的e就是吃了3个苹果后的126,我要知道多了几斤,就要用126-120,你理解下这段话,就能理解博主的意图,意思就是说,对象e的作用是进过一段计算后,和对象c来对比的!

        你理解了我新建2个两个一模一样的Cyc对象的目的后,咱们看下面的代码

#include <iostream>
#include <windows.h>
using namespace std;
// #include "head.h"
class Cyc{
    int a,b;
    public:
        Cyc(int x,int y){
            a=x;b=y;
        };
        void getAB(){
            cout<<"a="<<a<<",b="<<b<<endl;
        };
};
// 程序的主函数
int main()
{
   Cyc c(1,2);
   c.getAB();
   Cyc e(1,2);
   e.getAB();
   return 0;
}

 嗯,到这里你会发现一个问题。看下面git演示,你定义c和e对象他们一样要走一遍构造函数,也就是走了2次!!!

        3、既然  Cyc c和Cyc e传参都是(1,2),我为啥要构造两次,我直接让e 拷贝一次c的值就好了呀,这个拷贝的过程就要在拷贝构造函数里执行,先看下面代码

#include <iostream>
#include <windows.h>
using namespace std;
// #include "head.h"
class Cyc{
    int a,b;
    public:
        Cyc(int x,int y){
            a=x;b=y;
            cout<<endl;
        };
        Cyc(const Cyc &obj){
            a=obj.a;
            b=obj.b;
        };
        void getAB(){
            cout<<"a="<<a<<",b="<<b<<endl;
        };
};
// 程序的主函数
int main()
{
   Cyc c(1,2);
   c.getAB();
   Cyc e=c;
   e.getAB();
   return 0;
}

 看下图,拷贝构造函数的作用就在这里。只进来一次构造函数。但是c和e对象值都初始化了!好了,别急继续往下,看

 ----------------分割线----------------      

 4、为啥你在网上教程里,上来就看到 指针*号如下,干啥用的,非用不可吗?

 来,我们构建以下场景!!!!!!!!

题目,我要定义A类的两个变量   a,和b,  手动输入 一串英文字符串,不管输入啥,打印出来

a的首字母都要改成q,(其实模拟首字母大写的意思,反正就是改变了),然后 b拷贝了a,但是b的首字母还是原来的(也就是用户输入啥,b就是啥);

你们自己做看看,然后看看下面博主写的代码,你去理解下博主代码的意思!

#include <iostream>
#include <windows.h>
using namespace std;
#define MAX 20
class A{
    char *str;
    public:
        A(char *sstr){
            str=new char[MAX];//开辟10个char 内存空间的
            strcpy(str,sstr);
        };
        //修改 字符串
        void edit(){
            str[0]='q';
        };
        //打印 字符串第一个字符
        void getNext(){
            cout <<*str<<endl;
        };
        ~A(){
            delete [] str;//释放内存
        }
};
// 程序的主函数
int main()
{
    SetConsoleOutputCP(65001);
    char c[MAX];
    cout<<"请输入用户名(英文):";
    cin.get(c,MAX);
    A a(c);
    A b=a;
    cout<<"修改前a的第一个字符是"<<endl;
    a.getNext();//修改前打印a第一个字符
    a.edit();//修改a
    cout<<"修改a后a的第一个字符是"<<endl;
    a.getNext();//打印a第一个字符
    cout<<"b第一个字符也跟着变了"<<endl;
    b.getNext();//打印b第一个字符
    return 0;
}

 正常没拷贝函数的话,他们的*str指针都指向同一个char[],的第一个位置,是同一个!!!!

这么说,可能会好理解写,str存了一个字符串,*str是指针,指向字符串第一个字符串,A b=a;所以 b的*str也指向了a *str所指向的这个字符。所以a *str指向改变了之后b也跟着变,博主理解 不懂对不对,感觉应该是    b的*str→a的*str->"cyc",也就是**str.(个人理解,不懂对错,手下留情。),因为这么理解好记点。

那怎么办,拷贝构造函数!!!;

 

#include <iostream>
#include <windows.h>
using namespace std;
#define MAX 20
class A{
    char *str;
    public:
        A(char *sstr){
            str=new char[MAX];//开辟10个char 内存空间的
            strcpy(str,sstr);
        };
        A(const A &obj){
            str =new char[MAX];
            strcpy(str,obj.str);
        };
        //修改 字符串
        void edit(){
            str[0]='q';
        };
        //打印 字符串第一个字符
        void getNext(){
            cout <<*str<<endl;
        };
        ~A(){
            delete [] str;//释放内存
        }
};
// 程序的主函数
int main()
{
    SetConsoleOutputCP(65001);
    char c[MAX];
    cout<<"请输入用户名(英文):";
    cin.get(c,MAX);
    A a(c);
    A b=a;
    cout<<"修改前a的第一个字符是"<<endl;
    a.getNext();//修改前打印a第一个字符
    a.edit();//修改a
    cout<<"修改a后a的第一个字符是"<<endl;
    a.getNext();//打印a第一个字符
    cout<<"b指向第一个字符不变"<<endl;
    b.getNext();//打印b第一个字符
    return 0;
}

 好了,博文原创,我估计这样写完,几年后在回来看,我自己应该可以理解的了。

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

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

相关文章

Vue+TS开发定长虚拟列表

1.定长虚拟列表 定义&#xff1a;虚拟列表也有叫无限滚动的&#xff0c;创建一个滚动列表来渲染大量数据 使用场景有大量数据需要渲染时。 **解决了什么问题&#xff1f;**大量数据需要渲染&#xff0c;例如Vue传统使用V-for遍历会创建大量Node节点&#xff0c;对于内存和渲染…

【AI 导航网站】为了更好的收集 AI 资源,我开发了一个 AI 导航网站

AI 导航网站 目前 AI 应用正呈迸发式增长&#xff0c;然而一个人获取资源的途径有限&#xff0c;对于目前存在的AI工具不能很好的收集总结&#xff0c;所以基于此&#xff0c;我开发了这个一个AI导航网站&#xff0c;希望通过它&#xff0c;收集出目前存在的热门的AI应用&…

(一)Springcloud-OpenFeign原理之集成改造原生Openfeign与简单使用

文章目录 1.和原生Openfeign的关系2.Springcloud-Openfeign的改造2.1 改造目标2.2 改造内容2.2.1 集成到Spring2.2.2 替换构造组件 2.3 初步集成使用2.4 支持的扩展点 文章将会介绍Springcloud-Openfeign对原生Openfeign的改造原因及方式&#xff0c;最后提供简单的使用案例及扩…

实验一 进程管理与进程同步

实验一 进程管理与进程同步 实验目的&#xff1a; 了解进程管理的实现方法&#xff0c;理解和掌握处理进程同步问题的方法。 实验内容&#xff1a; 实现银行家算法、进程调度过程的模拟、读者-写者问题的写者优先算法。 实验步骤&#xff1a; 1.银行家算法流程图 &…

Springboot +Flowable,任务认领和回退(一)

一.简介 有的时候&#xff0c;一个任务节点会存在多个候选人&#xff0c;例如&#xff1a;张三提交一个任务&#xff0c;这个任务即可以由李四处理&#xff0c;又可以由王五处理&#xff0c;那么针对这种多个任务候选人的情况&#xff0c;该如何处理&#xff1f; 二.绘制流程…

Java线程池及其实现原理

线程池概述 线程池&#xff08;Thread Pool&#xff09;是一种基于池化思想管理线程的工具&#xff0c;经常出现在多线程服务器中&#xff0c;如MySQL。 线程过多会带来额外的开销&#xff0c;其中包括创建销毁线程的开销、调度线程的开销等等&#xff0c;同时也降低了计算机…

Spark任务提交流程

1. yarn-client Driver在任务提交的本地机器上运行&#xff0c;Driver启动后会和ResourceManager通讯&#xff0c;申请启动ApplicationMaster; 随后ResourceManager分配Container&#xff0c;在合适的NodeManager上启动ApplicationMaster&#xff0c;此时的ApplicationMaster的…

华为网络设备+WinRadius 实现用户统一管理设备

一、直接贴配置 ###配置VTY用户界面所支持的协议、验证方式 user-interface vty 0 4 protocol inbound telnet authentication-mode aaa quit ###配置RADIUS认证 ###&#xff08;1&#xff09;配置RADIUS服务器模板&#xff0c;指定服务器的IP地址与端口号、共享密钥 radius-s…

Supervisor离线安装(python3.7.8)

Background supervisor是用Python语言开发的一套通用的进程管理程序&#xff0c;可以将一个普通的命令行进程变为后台daemon&#xff0c;并监控进程状态&#xff0c;异常退出时可以自动拉起&#xff1b;可在大多数unix系统上使用&#xff0c;不能在windows上运行&#xff1b;目…

学Python常逛的10个网站

这里写目录标题 一、Python官方文档二、牛客网三、Github四、w3school五、Chatgpt六、kaggle七、realpython八、medium九、stackoverflow十、geeksforgeeks 一、Python官方文档 最全面的Python学习网站非官方文档莫属&#xff0c;它不仅提供了下载安装教程、基础语法教程、标准…

编写UDP版本的客户-服务器程序(echo server 和 echo client)

目录 前言概要 关于数据报流的关键方法签名 UDP协议传输案例 服务端&#xff08;接收端&#xff09; 服务端完整代码 客户端(发送端) 客户端完整代码 创作不易多多支持&#x1f636;‍&#x1f32b;️&#x1f618; 前言概要 我们首先来了解一下, 什么是网络编程. 网络编程…

认识系统总线

目录 一、总线的基本概念 1.总线的定义 二、总线的分类 1.片内总线 2.系统总线 2.1数据总线 2.2地址总线 2.3控制总线 3.通信总线(通信总线) 三、总线特性及性能指标 1.总线特征 2.性能标准 2.1总线的传输周期(总线周期) 2.2总线时钟周期 2.3总线的工作频率 2.4…

vim编辑器命令模式——撤销与时间旅行

Vi介绍 Vi 编辑器是所有 Unix 及 Linux 系统下标准的编辑器&#xff0c;类似于 windows 系统下的 notepad &#xff08;记事本&#xff09;编辑器&#xff0c;由于在 Unix 及 Linux 系统的任何版本&#xff0c;Vi 编辑器是完全相同的&#xff0c;因此可以在其他任何介绍 vi 的地…

小红书数据,如何在垂类赛道中脱颖而出!

导语 近年来&#xff0c;泛娱乐内容在小红书平台盛行&#xff0c;面临流量见顶的情况。这时候&#xff0c;垂类账号的优势就显现出来&#xff0c;不仅可以规避激烈的竞争&#xff0c;还能去获取更精准的流量。 作为一个经久不衰的创作方向&#xff0c;美食赛道分化出教程、测…

webpack plugin原理以及自定义plugin

通过插件我们可以拓展webpack&#xff0c;加入自定义的构建行为&#xff0c;使webpack可以执行更广泛的任务。 plugin工作原理&#xff1a; webpack工作就像是生产流水线&#xff0c;要通过一系列处理流程后才能将源文件转为输出结果&#xff0c;在不同阶段做不同的事&#x…

核磁机器学习 | 基于机器学习的fMRI分类

导读 本文通过提取最显著的特征&#xff0c;将大脑图像分类为正常和异常&#xff0c;并对大脑各种状态的磁共振成像(MRI)进行了研究。本文描述了一种基于小波变换的方法&#xff0c;首先对图像进行分解&#xff0c;然后使用各种特征选择算法从MRI图像中提取最显著的大脑特征。…

[Netty] 面试问题 1 (十八)

文章目录 1.Netty的特点2.Netty应用场景3. Netty核心组件4.Netty的线程模型5. EventloopGroup和EventLoop6.Netty 的零拷贝7.Netty 长连接和心跳机制8.Netty 服务端和客户端的启动过程9.Netty 的 Channel 和 EventLoop10.Netty 的 ChannelPipeline11.Netty 中的 ByteBuf12.Nett…

数据分析01——Anaconda安装/Anaconda中的pip换源/jupyter配置

0、前言&#xff1a; 数据分析三大模块知识&#xff1a;numpy&#xff08;数组计算&#xff09;、pandas&#xff08;基于numpy开发&#xff0c;用于数据清洗和数据分析&#xff09;、matplotlib&#xff08;实现数据可视化&#xff09; 1、Anaconda安装&#xff1a; 安装Ana…

Spring常见面试题总结(2023最新版)

文章目录 1、谈谈你对Spring的理解&#xff1f;1.1 发展历程1.2 Spirng的组成1.3 Spring的好处 2、Autowired和Resource的区别2.1 共同点&#xff1a;2.2 Autowired2.3 Resource2.3.1 Resource的装配顺序 3、Spring常用注解3.1、给容器中注入组件3.1.1 包扫描组件标注注解3.1.2…

Faster-RCNN跑自己的数据集(详细过程)FPN学习

1、下载b站 &#xff1a;霹雳吧啦Wz 的代码 github链接&#xff1a;https://github.com/WZMIAOMIAO/deep-learning-for-image-processing 对应视频链接&#xff1a;2-自定义DataSet_哔哩哔哩_bilibili 2、配置环境&#xff0c;安装相应的包。 或者如果有报错可以直接更新重新…