类的浅度复制和深度复制

现在我们定义一个类

//name.h

class name

{

private:

char *str;

int len;

static in num_name; //全局变量,不能在声明中初始化。(因为声明描述了如何分配内存,但不分配内存)。

public:

name();

name(const char* s);

name(const name& s);

~name();

}

//name.cpp

#include <cstring>

#include <iostream>

using namespace std;

int name::num_name = 0;

name::name()

{

len = 4;

str = new char[len+1];

strcpy(str,"c++");

num_name ++‘

}

name::name(const char* s)

{

len = strlen(s);

str = new char[len+1];

strcpy(str, s);

num_name ++;

}

name::~name()

{

num_name--;

delete [] str;

}

我们把一个对象赋给另一个对象的时候会调用类的(默认的)隐式复制构造函数。默认的复制构造函数不说明其行为,因此它不指出创建过程,也不增加计数器的num_name的值,

但是析构函数更新了计数,并且在任何对象过期时都会被调用,而不管对象是如何被创建的。

所以,我们应该自己显示定义复制构造函数。

name::name(const name& s) //显示复制构造函数

{

num_name++;

............

}

下一个异常更微妙,隐式复制构造函数,是浅复制,对于指针类型相当于:对象A.str = 对象B.str,这种复制只是把B的字符串地址赋给A的字符串,这两个字符串指向同一字符串的同一地址,

对象A调用析构函数释放str,当对象B调用析构函数释放str的是已经被释放了的地址,这样会造成意想不到的错误,为了让对象都释放自己的字符串,所以要让对象都拥有自己的字符串,

我们要对字符串进行深度(deep)复制。

复制函数要这样写:

name::name(const name& s)

{

num_name ++;

len = s.len;

str = new char[len+1];

strcpy(str, s.str);

}

注意:如果类中包含了使用new初始化的指针成员,应当定义一个复制构造函数,以复制指向的数据,而不是指针,这被称为深度复制。复制的另一种形式(成员复制或浅复制)只是复制指针指,

浅复制仅浅浅的复制指针信息,而不会深入“挖掘”来复制指针引用的结构。

时间: 2024-11-07 19:47:07

类的浅度复制和深度复制的相关文章

浅度复制VS深度复制

对于引用类型的复制,通过MemberwiseClone()复制的只是引用,即myclone1和myclone2的myContent是相同的对象实例.一个改变值,另一个也会改变.因为myContent.Val是公共字段. 值对象则没有这种顾虑 PS:感觉ICloneable 接口并没有什么用,完全可以自己写方法.毕竟ICloneable里面只有一个Clone方法. 代码如下: 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 C

转载---Java集合对象的深度复制与普通复制

原博文:http://blog.csdn.net/qq_29329775/article/details/49516247 最近在做算法作业时出现了错误,原因是没有弄清楚java集合的深度复制和浅度复制的区别. 1.首先是对Java集合对象得浅复制与深度复制的理解 普通的集合复制只是将内存中栈的地址快拷贝一份,使得一个新的集合对象指向这个地址块,但是集合中的对象变量却是指向堆中的同一块区域.所以当拷贝的集合修改了集合对象内的数据,那么源集合对象也就随之改变了,这样的效果我们称之为Java集合对象

对象的复制(浅复制与深复制)

在Java中如果想将一个基本类型变量的值赋给另一个变量,直接使用等号解可以了,原始的版本改变了,副本并不会发生变化,如下: int a=10; int b=a; a=9; System.out.println(a); //9 System.out.println(b); //10 但是如果想要复制的变量不是基本类型,而是引用类型的话,就会与上面的效果不同: package demos; /** * Created by hu on 2016/3/26. */ public class Peopl

.NET基础之深度复制和浅度复制

之前一直没有搞清楚深度复制和浅度复制的区别到底在哪里,今天彻底把这个东西弄懂了,写出来与到家共勉. 大家都知道Object是所有类共同的基类,其有个方法是MemberwiseClone(),其用途为 我们可以通过这个方法来达到浅度复制的效果. 下面我们通过一个例子来阐述一下浅度复制,其与深度复制的区别在什么地方: public class Content { public int Val; } public class Cloner { public Content MyContent = ne

深度复制与浅度复制

浅度复制:只是复制类的值类型字段和引用类型字段的引用 深度复制:即完全复制过来,不管里面的值类型字段还是引用类型字段,是构成一个全新的一模一样的对象. 代码: 1 public class PersonInfo 2 { 3 public string Name{get;set;} 4 public int Age{get;set;} 5 } 6 public class Person : ICloneable 7 { 8 public PersonInfo PersonInfo { get; s

(原创)c#学习笔记09--定义类08--浅度和深度复制

9.8  浅度和深度复制 从一个变量到另一个变量按值复制对象,而不是按引用复制对象(即以与结构相同的方式复制)可能非常复杂.因为一个对象可能包含许多其他对象的引用,例如,字段成员等,这将涉及许多繁琐的操作.把每个成员从一个对象复制到另一个对象中可能不会成功,因为其中一些成员可能是引用类型. .NET Framework 考虑了这个问题.简单地按照成员复制对象可以通过派生于System.Object的MemberwiseClone()方法来完成,这是一个受保护的方法,但很容易在对象上定义一个调用该

IT十八掌作业_java基础第十五天_IO串行化/深度复制

1.使用RandomAccessFile实现文件合成. 2.使用java中的串行化技术实现对象图(100只猫Cat集合,但是Cat的owner不需要串行化)的深度复制. 3.阐述串行化的过程,应用场景,串行ID的用途. 1. package com.it18zhang; /** * 将分割的文件进行合成 */ import java.io.File; import java.io.FileInputStream; import java.io.RandomAccessFile; public c

Java基础第十五天_IO串行化/深度复制

1.使用RandomAccessFile实现文件切割. 答: package app_作业; import java.io.File; import java.io.FileOutputStream; import java.io.RandomAccessFile; public class app15_使用RandomAccessFile实现文件切割 { public static void main(String[] args) throws Exception { // 源文件 File 

【Stack Overflow -- 原创加工、原创整理、生产实战】-- 深度复制

一.说明 1.本程序的核心代码不是我原创的,是我在Stack Overflow上搜集后加工出来的,原作者已忘记了~ 2.这段程序是我在上海携程(2014年左右)上班时整理并在生产环境应用的,先后经历了三家公司项目中使用,稳定可靠,放心使用 3.扩展方法部分可根据自己实际需要修改,流可以搞个static,pool,也可以每次 new,根据项目性能需求自己定制就行了 二.代码 代码如下: 核心类  NonSerialiazableTypeSurrogateSelector : 1 /// <summ