首页 > 编程语言 >C++ 深拷贝浅拷贝

C++ 深拷贝浅拷贝

时间:2024-02-19 18:45:49浏览次数:15  
标签:int age C++ Person age1 拷贝 ptr

C++ 深拷贝浅拷贝

C++默认生成的拷贝构造函数,他的行为就是浅拷贝,他只会复制一个一模一样的的指针,并不会操作指针指向的东西。
要想实现我们的逻辑需求,就要自定义拷贝构造函数,实现深拷贝。

我们来具体说明一下上面的话
首先我们创建一个简单的类

#include <iostream>
using namespace std;
class Person{
  public:
  Person(int age1):age(age1),m_ptr(nullptr)
  {
    if(age1>0)
      m_ptr=(int*)malloc( age1 );
  }
  ~Person()
  {
    free(m_ptr);
    m_ptr=nullptr;
  }
  private:
  int * m_ptr;
  int age;
};

int main() 
{
Person p1(10);
Person p2 = p1;
return 0;
}

这个时候就会发现编译没有问题,但是一旦运行就会报错。
这个是因为系统的默认拷贝构造是浅拷贝,把p1成员指针的内容复制给p2成员指针,导致这两个指针都指向的同一个内存地址
然后p1先调用析构函数,内存释放,接下来p2也会调用析构函数,但是由于p1已经释放了内存地址,该地址为空又调用free函数就会引发异常
这个时候我们需要自己实现拷贝构造函数,写一个深拷贝:

//修改后的代码
#include <iostream>
using namespace std;

class Person{
  public:

  Person(int age1):age(age1),m_ptr(nullptr)
  {
    if(age1>0)
      m_ptr=(int*)malloc( age1 );
  }
  
  Person(const Person& p):age(p.age),m_ptr(nullptr)
  {
    if(p.age>0)
      m_ptr=(int*)malloc( p.age );
  }
  Person& operator=(const Person& p)
  {
    if(this == &p) //避免自我赋值
    {return *this;}
    free(m_ptr);
    age=p.age;
    m_ptr = (int*)malloc(p.age);
    return *this;
  }
  ~Person()
  {
    free(m_ptr);
    m_ptr=nullptr;
  }
  private:
  int * m_ptr;
  int age;
};

int main() 
{
Person p1(10);
Person p2 = p1;
return 0;
}

这个时候运行就不会产生异常,这就是深拷贝和浅拷贝

标签:int,age,C++,Person,age1,拷贝,ptr
From: https://www.cnblogs.com/AndreaDO/p/18021519

相关文章

  • 线性插值计算百分位数的C++示例
    代码如下#include<iostream>#include<vector>#include<algorithm>doublepercentile_linear_interpolation(conststd::vector<double>&data,doublepercentile){//确保百分位数在合理范围内if(percentile<0.0||percentile>1......
  • C/C++ 宏区分不同系统、编译器、语言版本
    目录区分不同系统区分不同编译器及其版本区分不同语言及其版本参考区分不同系统1)_WIN32,Windows系统_WIN64:32bitand64bit系统M_WIN64:仅64bitWindows系统M_WIN32:仅32bitWindows系统_WINDOWS:GUIApplication_CONSOLE:consoleApplication2)__APPLE__,苹果系统,包括MAC、IOST......
  • VC++ 中 CT2A CA2T 两个宏进行字符串转换简单测试
    #include"afxwin.h"#include<iostream>usingnamespacestd;intmain(){CStringcs=_T("西游记");AfxMessageBox(_T("CString:")+cs);//CString转ACSIICT2Aa_str(cs);stringstd_str(a_str);......
  • KY78 最大上升子序列和C++
    这个解决问题的思路使用动态规划,即用已知状态去得到未知状态。思路逻辑是这样sum[i]记录以A[i]为末上升子序列的和的最大值然后从j从0-i-1遍历如果A[j]<A[i]那么sum[i]=sum[j]+A[i];然后找出sum[i]中的的最大值,就是以A[i]为末上升子序列的和的最大值。这样就实现了从前......
  • FUN GAME 一款普通的C++游戏
    凑合看吧,不是完整版。#include<bits/stdc++.h>#include<windows.h>#include<conio.h>usingnamespacestd;#defineptputs#definepfprintf#definepcputchar#definesfscanf#definegtgets#defineslSleepcharname[101];stack<int>gun;bo......
  • 15. C++类中成员变量的初始化总结
    C++类中成员变量的初始化总结1.普通的变量:一般不考虑啥效率的情况下可以在构造函数中进行赋值。考虑一下效率的可以再构造函数的初始化列表中进行。classCA{public:intdata;public:CA();};/*********/CA::CA():data(0)//……#1……初始化列表方式{......
  • KY148 还是畅通工程C++
    求图的最小生成树。克鲁斯卡尔算法来解决。就是选择n-1条最小边且无回路。回路判断用并查集就行。即要加入的边(两个节点)具有相同的父节点说明如果这两个节点本来就存在路径,再加入一条边就会产生回路,舍去。#include<iostream>#include<algorithm>usingnamespacestd;struc......
  • C++ 模板的笔记1
    C++模板的笔记1C++函数模板函数模板的定义函数模板是一种可以生成不同类型函数的函数声明。函数模板的参数类型不是固定的,而是在调用时由实参类型推导出来。语法:template<typename参数列表>函数返回值类型函数名(参数列表){函数体}示例:template<typenameT>vo......
  • 【c&c++】cJSON详解
    一、JSON概述1.1JSON介绍JSON:JavaScript对象表示法(JavaScriptObjectNotation)。是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。JSON采用完全独立于语言的文本格式,但是也使用了类似C语音家族的习惯(包括C、C++、C#、Java、JavaScript、Perl、Python等)。这些特性使JSON......
  • 阅读下面 C++ 代码,输出结果为()
    #include<iostream>usingnamespacestd;classbase1{private:inta,b;public:base1(inti):b(i+1),a(b){}base1():b(0),a(b){}intget_a(){returna;}intget_b(){returnb;}};intmain()......