C++简明图解分析浅拷贝与深拷贝

 更新时间:2022年06月02日 10:17:37   作者:Bright-SKY  
在c++中,深拷贝和浅拷贝也算是一个难点,特别是对于初学者来说,往往在不知道两者区别的情况下而错误的使用了浅拷贝,从而导致了野指针之类的问题,但是又因为缺少理解所以很难定位到问题所在

类中有指针成员 才会讨论 浅拷贝 和深拷贝问题。

浅拷贝(单纯值拷贝)

#include <iostream>
#include <string.h>
#include <stdlib.h>
using namespace std;
class Person
{
public:
    char *m_name;
public:
    Person(char *name)
    {
        cout<<"有参构造"<<endl;
        m_name = (char *)calloc(1,strlen(name)+1);
        if(m_name == NULL)
        {
            cout<<"空间申请失败"<<endl;
            exit(-1);
        }
        strcpy(m_name, name);
    }
    ~Person()
    {
        cout<<"析构函数"<<endl;
        //释放指针成员 指向的堆区空间
        if(m_name != NULL)
        {
            free(m_name);
            m_name = NULL;
        }
        cout<<"-----001------"<<endl;
    }
};
int main(int argc, char *argv[])
{
    Person ob1("lucy");
    Person ob2 = ob1;//拷贝构造(默认是浅拷贝)
    cout<<"ob2.m_name = "<<ob2.m_name<<endl;
    return 0;
}

深拷贝

必须在拷贝构造中给ob2.m_name申请空间

#include <iostream>
#include <string.h>
#include <stdlib.h>
using namespace std;
class Person
{
public:
    char *m_name;
public:
    Person(char *name)
    {
        cout<<"有参构造"<<endl;
        m_name = (char *)calloc(1,strlen(name)+1);
        if(m_name == NULL)
        {
            cout<<"空间申请失败"<<endl;
            exit(-1);
        }
        strcpy(m_name, name);
    }
    Person(const Person &ob)
    {
        cout<<"拷贝构造函数(深拷贝)"<<endl;
        m_name = (char *)calloc(1, strlen(ob.m_name)+1);
        if(m_name == NULL)
        {
            cout<<"空间申请失败"<<endl;
            exit(-1);
        }
        strcpy(m_name, ob.m_name);
    }
    ~Person()
    {
        cout<<"析构函数"<<endl;
        //释放指针成员 指向的堆区空间
        if(m_name != NULL)
        {
            free(m_name);
            m_name = NULL;
        }
    }
};
int main(int argc, char *argv[])
{
    Person ob1("lucy");
    Person ob2 = ob1;//拷贝构造
    cout<<"ob2.m_name = "<<ob2.m_name<<endl;
    return 0;
}

总结

1、如果类中的成员 指向了堆区空间 一定要记得在析构函数中 释放该空间

2、如果用户 不实现 拷贝构造 系统就会提供默认拷贝构造,而默认拷贝构造 只是单纯的赋值 容易造成浅拷贝问题

3、用户记得 要实现:无参构造(初始化数据)、有参构造(赋参数)、拷贝构造(深拷贝) 、析构函数(释放空间)

拷贝构造函数的调用时机

拷贝构造函数调用的时机:旧对象 给新对象 初始化

class Data
{
public:
    Data()
    {
        cout<<"无参构造"<<endl;
    }
    Data(const Data &ob)
    {
        cout<<"拷贝构造"<<endl;
    }
    ~Data()
    {
        cout<<"析够函数"<<endl;
    }
};

情形1:旧对象给新对象初始化

Data ob1;
Data ob2 = ob1;//调用拷贝构造

情形2:普通对象作为函数的参数

void fun01(Data ob)//Data ob=ob1  发生拷贝构造
{
}
int main(int argc, char *argv[])
{
    Data ob1;
    fun01(ob1);
    return 0;
}

情形3:普通对象 作为函数的返回值

#include <iostream>
using namespace std;
Data fun01(void)
{
    Data ob1;
    return ob1;
}
int main(int argc, char *argv[])
{
    Data ob = fun01();
    return 0;
}

vs下会发生拷贝构造:

Qt、linux不会发生拷贝:

到此这篇关于C++简明图解分析浅拷贝与深拷贝的文章就介绍到这了,更多相关C++浅拷贝与深拷贝内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++实现模板中的非类型参数的方法

    C++实现模板中的非类型参数的方法

    这篇文章主要介绍了C++实现模板中的非类型参数的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • C++实现LeetCode(45.跳跃游戏之二)

    C++实现LeetCode(45.跳跃游戏之二)

    这篇文章主要介绍了C++实现LeetCode(45.跳跃游戏之二),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • c语言函数栈帧的创建和销毁过程详解

    c语言函数栈帧的创建和销毁过程详解

    我们知道c语言中函数都是被调用的,main函数里面能调用其他函数,其实main函数也是被别的函数调用的,下面通过本文给大家分享c语言函数栈帧的创建和销毁过程,一起看看吧
    2021-08-08
  • boost字符串处理函数format的用法

    boost字符串处理函数format的用法

    这篇文章介绍了boost字符串处理函数format的用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • c++报错问题解决方案lvalue required as left operand of assignment

    c++报错问题解决方案lvalue required as left opera

    这篇文章主要介绍了c++报错:lvalue required as left operand of assignment,出现此错误原因,是因为,等号左边是不可被修改的表达式或常量,而表达式或常量不能作为左值,需要的朋友可以参考下
    2023-01-01
  • C++深入细致探究二叉搜索树

    C++深入细致探究二叉搜索树

    二叉搜索树是以一棵二叉树来组织的。每个节点是一个对象,包含的属性有left,right,p和key,其中,left指向该节点的左孩子,right指向该节点的右孩子,p指向该节点的父节点,key是它的值
    2022-05-05
  • C++ decltype类型说明符

    C++ decltype类型说明符

    在C++中,decltype作为操作符,用于查询表达式的数据类型。decltype在C++11标准制定时引入,主要是为泛型编程而设计,以解决泛型编程中,由于有些类型由模板参数决定,而难以(甚至不可能)表示之的问题。
    2016-03-03
  • C语言中十六进制转十进制两种实现方法

    C语言中十六进制转十进制两种实现方法

    这篇文章主要介绍了C语言中十六进制转十进制两种实现方法的相关资料,需要的朋友可以参考下
    2017-01-01
  • C++ 内存泄漏调试方式

    C++ 内存泄漏调试方式

    这篇文章主要介绍了C++ 内存泄漏调试方式,C++和其他高级语言不同,需要自行管理内存,项目大调用多,下文我们就来看看C++ 内存泄漏调试方式分享,需要的小伙伴可以参考一下
    2022-04-04
  • 初识C++ Vector模板与实例化原理

    初识C++ Vector模板与实例化原理

    这篇文章主要为大家介绍了初识C++ Vector模板与实例化原理,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12

最新评论