C++拷贝对象
简介
对象的创建中,常常有这样的需求,就是把对象复制一份。
而复制有三种方法:
1.通过初始化来复制
例如:Object o1(10); Object o2=o1;
2.通过赋值来复制
例如:Object o1(10); Object o2; o2=o1;
3.通过默认拷贝函数来复制
例如:Object o1(10); Object o2(o1);
实际上,第一种方法内部原理是执行了第三种的拷贝函数,默认的拷贝函数是浅拷贝,也就是说只能对基本类型数值进行拷贝
Object类如下:
class Object
{
private:
int _num;
public:
Object(int num)
{
_num=num;
}
};
分析
第一种复制对象方法原理(初始化复制)
1.首先 Object o2=o1 这句是先执行了o1的默认拷贝函数
此处o1的默认拷贝函数申明为: Object(const Object& obj),该实现体为编译器默认的浅复制方法实现,因此对于含有复杂变量的类,需要重写该函数
2.然后执行o1的拷贝函数后返回一个匿名对象
3.最后将该匿名对象命名为o2
第二种复制方法原理(赋值复制)
*该原理较为简单,就是直接将简单基本变量值拷贝一份赋值给拷贝对象
第三种复制方法原理(拷贝函数复制)
*第一种原理已解释
实例
代码
Object.h
class Object
{
private:
int _num;
public:
Object(int num)
{
_num=num;
}
int getNum()
{
return _num;
}
};
main.cpp
#include <iostream>
#include "Object.h"
using namespace std;
int main(int argc, char** argv) {
Object o1(10);
Object o2=o1;
cout<<o2.getNum()<<endl;
Object oo1(20);
Object oo2(10);
oo2=oo1;
cout<<oo2.getNum()<<endl;
Object ooo1(30);
Object ooo2(ooo1);
cout<<ooo2.getNum()<<endl;
return 0;
}
运行结果
提升
代码
Object.h
#ifndef OBJECT_H
#define OBJECT_H
#include <stdlib.h>
#include <string.h>
class Object
{
private:
char *_name;
public:
Object(char *name)
{
_name=(char*)malloc(sizeof(char)*(strlen(name)+1));
strcpy(_name,name);
}
};
#endif
main.cpp
#include <iostream>
#include "Object.h"
using namespace std;
void Test()
{
Object o1("test");
Object o2(o1);
}
int main(int argc, char** argv) {
Test();
return 0;
}
*这段代码在较为严格的编译器中会报错,这是因为默认拷贝函数是浅拷贝,对基本的值进行拷贝
*然而o2拷贝o1的值时,拷贝的是_name的值,在栈中也就是字符串的地址值,因此拷贝后的o2的_name只是引用了o1的_name指向的字符串
*因此在Test函数结束时,首先o2被析构,其_name指向的字符串被回收。然后o1被析构,其_name指向的字符已在o2析构时被回收,因此o1的_name是野指针,因此产生错误。
改进代码
Object.h
#ifndef OBJECT_H
#define OBJECT_H
#include <stdlib.h>
#include <string.h>
class Object
{
private:
char *_name;
int _num;
public:
Object(int num,char *name)
{
_num=num;
_name=(char*)malloc(sizeof(char)*(strlen(name)+1));
strcpy(_name,name);
}
Object(const Object& obj)
{
_name=(char*)malloc((sizeof(char)*strlen(obj._name)+1));
strcpy(_name,obj._name);
}
};
#endif
C++拷贝对象的更多相关文章
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象. 2. copy.deepcopy 深拷贝 拷贝对象及其子对象 一个很好的例子: # -*-coding:utf-8 -*- ...
- 夺命雷公狗—angularjs—23—copy拷贝对象
copy这在angularjs中是一个拷贝对象的方法: <!DOCTYPE html> <html lang="en" ng-app="myapp&qu ...
- 使用copy来拷贝对象
拷贝对象 您通过将 copy 消息发送给对象,以制作对象的副本. NSArray *myArray = [yourArray copy]; 要拷贝,接收对象的类必须遵守 NSCopying 协议.如果 ...
- Java 使用反射拷贝对象一般字段值
在<Java解惑>上面看到第八十三例--诵读困难者,要求使用非反射实现单例对象的拷贝.查阅了部分资料,先实现通过反射拷贝对象. 1. 编写需要被拷贝的对象Person package co ...
- 读书笔记 effective c++ Item 12 拷贝对象的所有部分
1.默认构造函数介绍 在设计良好的面向对象系统中,会将对象的内部进行封装,只有两个函数可以拷贝对象:这两个函数分别叫做拷贝构造函数和拷贝赋值运算符.我们把这两个函数统一叫做拷贝函数.从Item5中,我 ...
- python中拷贝对象的区别
一.赋值.引用 在python中赋值语句总是建立对象的引用值,而不是复制对象.因此,python变量更像是指针,而不是数据存储区域 这点和大多数语音类似吧,比如C++.Java等 1.先看个例子: v ...
- c# 表达式目录树拷贝对象(根据对象类型动态生成表达式目录树)
表达式目录树,在C#中用Expression标识,这里就不介绍表达式目录树是什么了,有兴趣可以自行百度搜索,网上资料还是很多的. 这里主要分享的是如何动态构建表达式目录树. 构建表达式目录树的代码挺简 ...
- 为什么阿里Java手册推荐慎用 Object 的 clone 方法来拷贝对象
图片若无法显示,可至掘金查看https://juejin.im/post/5d425230f265da039519d248 前言 在阿里Java开发手册中,有这么一条建议:慎用 Object 的 cl ...
- C#实现拷贝对象
大家都知道,在C#中变量的存储分为值类型和引用类型两种,而值类型和引用类型在数值变化是产生的后果是不一样的,值类型我们可以轻松实现数值的拷贝,那么引用类型呢,在对象拷贝上存在着一定的难度. 下 ...
随机推荐
- 仿《雷霆战机》飞行射击手游开发--GameObject
转载请注明:http://www.cnblogs.com/thorqq/p/5646509.html 在上一篇中,我们介绍了各种游戏对象的功能及类的集成关系,现在我们来看看GameObject的源代码 ...
- [java学习笔记]java语言基础概述之内存的划分&堆和栈
1.内存的划分 1.寄存器 cpu处理 2.本地方法区 和所在系统相关 3.方法区 方法加载进内存,其实就是开辟了一块该方法的方法区 方法区中还可以有静态区,用于存放静态变量(类变量) 4.栈内存 5 ...
- linux 硬盘相关命令学习
summary: 查看硬盘信息:几块硬盘,品牌,容量 查看分区信息 参考资料: Linux下查看磁盘分区命令详解: http://blog.chinaunix.net/uid-26119273-id- ...
- qml去标题栏
只要加入"flags: Qt.Window | Qt.FramelessWindowHint "属性就可实现去标题栏. 注意:在使用这个属性的时候要先导入QtQuick.Windo ...
- CSS3单位
em 做前端的应该对em不陌生,不是什么罕见的单位,是相对单位,参考物是父元素的font-size,具有继承的特点.如果字体大小是16px(浏览器的默认值),那么 1em = 16px. 不过,这样使 ...
- 【转】 .NET中STAThread和MTAThread
ref:http://blog.csdn.net/dyllove98/article/details/9735955 1 COM中的公寓 本文讨论进程内COM组件.以一个示例直观演示STAThread ...
- 解决xtraFinder在EI下不能使用问题
在EI (10.11)下,由于SIP(System Integrity Protection)机制,导致一些第三方插件不能使用,如xtrafinder. 要想使用,在目前的情况下,启用的方法:一种是安 ...
- Demo学习: FileUpload
FileUpload 文件上传,学习TUniFileUpload控件的使用 TUniFileUpload主要属性: Filter: 文件类型过滤,这个属性在web模式下是无效的,UniGUI目前版本还 ...
- Linux分类笔记(一)-权限管理
Linux分类笔记(一) 权限管理 普通权限 文件的普通权限 对一个普通的文件使用ls -ll命令后,看到下面的输出内容 而对于文件权限中的每一位,又分别代表了以下的意思 文件类型又有以下几类: ...
- LeetCode之Single Number以及拓展
Problem 1:一个数组中有一个数字a只出现一次,其他数字都出现了两次.请找出这个只出现一次的数字? 考察知识点:异或运算 思路:比如数字 b^b = 0 a^0 = a 因此,可以将数组 ...