C++对象的浅复制和深复制详解及简单实例

C++对象的浅复制和深复制详解及简单实例

浅复制:两个对象复制完成后共享某些资源(内存),其中一个对象的销毁会影响另一个对象

深复制:两个对象复制完成后不会共享任何资源,其中一个对象的销毁不会影响另一个对象

下面我们来看一段代码,以便直观的理解:

#include<iostream>
#include<string.h>
using namespace std;
class Student
{
  int no;
  char *pname;
public:
  Student();
  Student(int n,char* p);
  ~Student();
  void display();
}; 

Student::Student(){} 

Student::Student(int n,char* p)
{
  no=n;
  pname=new char[10];
  strcpy(pname,p);
} 

Student::~Student()
{
  delete []pname;
} 

void Student::display()
{
  cout<<"学号:"<<no<<",姓名:"<<pname<<endl;
} 

void main()
{
  Student s(10,"xiaoming"),t;
  t=s;
  cout<<"s=";
  s.display();
  cout<<"t=";
  t.display();
}

这段程序看上去是正确的,但是执行就会出错,原因就是复制语句t=s,此语句执行的复制是浅复制,s将pname指针指向的地址赋给s的pname,它们就会指向相同的内存空间,当t被析构时,t.pname所指的内存空间就被释放了,再执行s的析构函数就会出错。

如果采用深复制就可以避免这个问题,下面我们用运算符重载函数实现深复制:

Student& Student::operator = (Student& s)
{
  no=s.no;
  int len=strlen(s.pname);
  pname=new char[len+1];
  strcpy(pname,s.pname);
  return *this;
}

在执行t=s时,运算符重载函数内已为t分配内存空间。

对于上述运算符重载函数有两点说明:

1.形参一定要是引用类型,否则执行t=s时,就要先将实参s复制到形参s,这个过程是浅复制,没有为形参s分配内存空间,运行会出错;

2.返回值一定要是引用类型,因为执行t=s相当于执行t.=(s),若返回值不是引用类型,那么还要将函数的返回对象复制到t,又会出错

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • 浅谈c++ vector和map的遍历和删除对象

    示例如下: // Aa.cpp : Defines the entry point for the console application. #include "stdafx.h" #include <vector> #include <map> #include <iostream> using namespace std; int main(int argc, char* argv[]) { printf("Hello World!\n

  • 用C++面向对象的方式动态加载so的方法

    这几天在写一个server,由于框架相同,仅仅是获取数据源的地方有区别,所以,研究了一下如何使用面向对象的方法来动态加载so. 主要思想就是: 1.通过一个函数能够获得一个基类的指针,这样在调用基类的函数的时候,就能自动调用子类的实现了. 2.存储so对象的指针应该是外层类的一个static变量. 详细还是看代码吧: 1)首先定义一个公共的头文件,里面存储的基类的定义:(需要注意的就是,只要不是纯虚函数,那么就一定要有实现:还有就是析构函数需要为虚函数) so和主调程序都需要包含这个头文件. s

  • C++ 中类对象类型的转化的实例详解

    C++ 中类对象类型的转化的实例详解 前言: 存在继承关系的类的对象之间可以进行转化: 子类对象类型可以转化为父类类型, 例如,一个函数的参数是父类对象,而传递进来的参数是子类对象,那么子类对象类型自动转化父类对象: 但是父类对象不能转为子类对象. 代码: # include <iostream> using namespace std; class A { public: void printm() { cout<<"A::print()"<<en

  • C#如何调用原生C++ COM对象详解

    前言 最近在工作中遇到一个问题,为了跨平台在.net core中使用COM,不能使用Windows下的COM注册机制,但是可以直接把IUnknown指针传给C#,转换为指针,再转换为C#的接口(interface). 做了这方面的研究,但最终我没有使用这套技术,因为对IDispatch::Invoke的分发太麻烦了,又不能借助ATL与VS开发环境的IDL能力.所以没有继续研究事件订阅(C#是event,C++COM是IConnectionPoint). C++中需要做的: 简单点,实现IDisp

  • C++使struct对象拥有可变大小的数组(详解)

    首先摘录<Inside The C++ Object Model>中的一段话: 把单一元素的数组放在一个struct的尾端,于是每个 struct objects 可以拥有可变大小的数组: struct mumble { char pc[1]; }; //获取一个字符串,然后为struct本身和该字符串配置足够的内存 struct mumble *pmumbl = (struct mumble*)malloc(sizeof(struct mumble) + strlen(string) + 1

  • 由static_cast和dynamic_cast到C++对象占用内存的全面分析

    static_cast和dynamic_cast是C++的类型转换操作符.编译器隐式执行的任何类型转换都可以由static_cast显式完成,即父类和子类之间也可以利用static_cast进行转换.而dynamic_cast只能用于类之间的转换.那么dynamic_cast的存在还有什么意义呢?因为dynamic_cast提供了一个重要的特性:运行时类型检查来保证转换的安全性. 用static_cast转换存在的危险 我们知道,一个基类指针不需要进行明确的转换操作,就可以指向基类对象或者派生类

  • c++ 面向对象的类设计

    类的设计在于用恰到好处的信息来完整表达一个职责清晰的概念,恰到好处的意思是不多也不少,少了,就概念就不完整:多了,就显得冗余,累赘,当然特例下,允许少许的重复,但是,这里必须要有很好的理由.冗余往往就意味着包含了过多的信息,概念的表达不够精准,好比goto,指针,多继承这些货色,就是因为其过多的内涵,才要严格限制其使用.好像,more effective c++上说的,class的成员函数,应该是在完整的情况下保持最小化.但是,这里我们的出发点,是成员数据的完整最小化. 最小化的好处是可以保持概

  • C++对象的浅复制和深复制详解及简单实例

    C++对象的浅复制和深复制详解及简单实例 浅复制:两个对象复制完成后共享某些资源(内存),其中一个对象的销毁会影响另一个对象 深复制:两个对象复制完成后不会共享任何资源,其中一个对象的销毁不会影响另一个对象 下面我们来看一段代码,以便直观的理解: #include<iostream> #include<string.h> using namespace std; class Student { int no; char *pname; public: Student(); Stud

  • VueJS设计与实现之浅响应与深响应详解

    正文 前文中讲完了如何响应Object,并处理了一些响应中的问题,但是我们目前,包括之前实现的响应式,其实只是浅响应. 直接上代码 const obj = {a:{b:1}} const reactive = (obj)=> new Proxy(obj,{ get(target,key,receiver){ /*省略其他逻辑*/ return Reflect.get(target,key,receiver) }, /*省略其他拦截*/ }) const data = reactive(obj)

  • MySQL 复制详解及简单实例

    MySQL 复制详解及简单实例 主从复制技术在MySQL中被广泛使用,主要用于同步一台服务器上的数据至多台从服务器,可以用于实现负载均衡,高可用和故障切换,以及提供备份等等.MySQL支持多种不同的复制技术,诸如单向,半同步异步复制等以及不同级别的复制,诸如数据库级别,表级,跨库同步等等.本文简要描述了一个基本的主从复制并给出示例. 1.复制的基本原理(步骤) a.在主库上把数据更改记录的二进制日志(binary log)     b.从库上的I/O线程连接到主库并请求发送其二进制日志文件(主库

  • Objective-C基础 自定义对象归档详解及简单实例

    自定义对象要实现归档必须实现NSCoding协议 NSCoding协议有两个方法,encodeWithCoder方法对对象的属性数据做编码处理,initWithCoder解码归档数据来初始化对象. 示例1 .h头文件 #import <Foundation/Foundation.h> @interface user : NSObject <NSCoding> @property(nonatomic,retain)NSString *name; @property(nonatomic

  • PHP对象的浅复制与深复制的实例详解

    PHP对象的浅复制与深复制的实例详解 最近在看原型模式时注意到这个问题~~PHP中对象 '=' 与'clone'的区别 实例代码: //聚合类 class ObjA { public $num = 0; public $objB;//包含的对象 function __construct() { $this->objB = new ObjB(); } //只有实现了下面方法聚合类 才能实现深复制 /*function __clone() { $this->objB = clone $this-&

  • php5对象复制、clone、浅复制与深复制实例详解

    本文实例讲述了php5对象复制.clone.浅复制与深复制.分享给大家供大家参考,具体如下: 对象复制的由来 为什么对象会有"复制"这个概念,这与PHP5中对象的传值方式是密切相关的,让我们看看下面这段简单的代码 PHP代码 /** * 电视机类 */ class Television { /** 屏幕高度 */ protected $_screenLength = 300; /** 屏幕宽度 */ protected $_screenHight = 200; /** 电视机外观颜色

  • PHP中的浅复制与深复制的实例详解

    PHP中的浅复制与深复制的实例详解 前言: 最近温习了一下Design Pattern方面的知识,在看到Prototype Pattern这一设计模式时,注意到其中涉及到一个浅复制与深复制的问题.这里来总结一下,提醒自己以后一定要多加注意. 自PHP5起,new运算符自动返回一个引用,一个 对象变量 已经不再保存整个对象的值,只是保存一个标识符来访问真正的对象内容.当对象作为参数传递,作为结果返回,或者赋值给另外一个变量,另外一个变量跟原来的不是引用的关系,只是他们都保存着同一个标识符的拷贝,这

  • 举例区分Python中的浅复制与深复制

    copy模块用于对象的拷贝操作.该模块非常简单,只提供了两个主要的方法: copy.copy 与 copy.deepcopy ,分别表示浅复制与深复制.什么是浅复制,什么是深复制,网上有一卡车一卡车的资料,这里不作详细介绍.复制操作只对复合对象有效.用简单的例子来分别介绍这两个方法. 浅复制只复制对象本身,没有复制该对象所引用的对象. #coding=gbk import copy l1 = [1, 2, [3, 4]] l2 = copy.copy(l1) print l1 print l2

  • Java 浅复制和深复制的实例详解

    Java 浅复制和深复制的实例详解 1 浅复制和深复制区别 浅复制:浅复制只是复制本对象的原始数据类型,如int.float.String,对于数组和对象引用等是不会复制的.因此浅复制是有风险的. 深复制:不但对原始数据类型进行复制,对于对象中的数组和对象引用也做复制的行为,从而达到对对象的完全复制. 2 代码示例 package com; import java.util.ArrayList; public class Test implements Cloneable { // 私有属性 p

  • JavaScript 赋值,浅复制和深复制的区别

    目录 1.变量赋值 1.1 原始值和引用值 1.2 赋值 二.浅复制(Shallow Copy) 2.1 原生 JavaScript 中的浅复制 Object.assign() 2.2 浅复制的手动实现 三.深复制(Deep Copy) 2.1 原生 JavaScript 中的深复制 JSON.parse(JSON.stringify(object)) 2.2 深复制的手动实现 小结 前言: 浅复制和深复制可以说是面试中很常见的一道题了,本文就来聊一聊JavaScript中的浅复制和深复制. 1

随机推荐