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

文章详细解释了C++中拷贝构造函数的概念,通过实例展示了为何需要使用拷贝构造函数来避免对象间的深层复制问题,以及如何防止因共享内存导致的数据错误。同时,文中通过字符串首字母修改的例子,说明了拷贝构造函数在处理指针成员时的重要性。

序:

        说实话,博主卡了一天,哎,老了。。。。理解能力不行。有时候还想着先跳过把,结果下班后,还在纠结是不是自己打开的方式不对,这不,刚理解了点,回来写下笔记,因为初学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;
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪狼之夜

打个赏,让博主知道博文没白写

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值