C++拷贝构造函数(深拷贝&浅拷贝)
对于普通类型的对象来说,它们之间的复制是很简单的,例如:
int a=88;
int b=a;
而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。下面看一个类对象拷贝的简单例子。
using namespace std;
class CExample {
private:
int a;
public:
CExample(int b)
{ a=b;}
void Show ()
{
cout<<a<<endl;
}
};
int main()
{
CExample A(100);
CExample B=A;
B.Show ();
return 0;
} 运行程序,屏幕输出100。从以上代码的运行结果可以看出,系统为对象B分配了内存并完成了与对象A的复制过程。就类对象而言,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。下面举例说明拷贝构造函数的工作过程。
using namespace std;
class CExample {
private:
int a;
public:
CExample(int b)
{ a=b;}
CExample(const CExample& C)
{
a=C.a;
}
void Show ()
{
cout<<a<<endl;
}
};
int main()
{
CExample A(100);
CExample B=A;
B.Show ();
return 0;
} CExample(const CExample& C)就是我们自定义的拷贝构造函数。可见,拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变量,该参数是const类型,不可变的。例如:类X的拷贝构造函数的形式为X(X& x)。
当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用。也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:
一个对象以值传递的方式传入函数体
一个对象以值传递的方式从函数返回
一个对象需要通过另外一个对象进行初始化。
如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝,后面将进行说明。
自定义拷贝构造函数是一种良好的编程风格,它可以阻止编译器形成默认的拷贝构造函数,提高源码效率。
浅拷贝和深拷贝
在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。
深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。下面举个深拷贝的例子。
#include <iostream>
using namespace std;
class CA
{
public:
CA(int b,char* cstr)
{
a=b;
str=new char[b];
strcpy(str,cstr);
}
CA(const CA& C)
{
a=C.a;
str=new char[a]; //深拷贝
if(str!=0)
strcpy(str,C.str);
}
void Show()
{
cout<<str<<endl;
}
~CA()
{
delete str;
}
private:
int a;
char *str;
};
int main()
{
CA A(10,"Hello!");
CA B=A;
B.Show();
return 0;
}
深拷贝和浅拷贝的定义可以简单理解成:如果一个类拥有资源(堆,或者是其它系统资源),当这个类的对象发生复制过程的时候,这个过程就可以叫做深拷贝,反之对象存在资源,但复制过程并未复制资源的情况视为浅拷贝。
浅拷贝资源后在释放资源的时候会产生资源归属不清的情况导致程序运行出错。
Test(Test &c_t)是自定义的拷贝构造函数,拷贝构造函数的名称必须与类名称一致,函数的形式参数是本类型的一个引用变量,且必须是引用。
当用一个已经初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用,如果你没有自定义拷贝构造函数的时候,系统将会提供给一个默认的拷贝构造函数来完成这个过程,上面代码的复制核心语句就是通过Test(Test
&c_t)拷贝构造函数内的p1=c_t.p1;语句完成的。
C++拷贝构造函数(深拷贝&浅拷贝)的更多相关文章
- 【转】 c++拷贝构造函数(深拷贝,浅拷贝)详解
c++拷贝构造函数(深拷贝,浅拷贝)详解 2013-11-05 20:30:29 分类: C/C++ 原文地址:http://blog.chinaunix.net/uid-28977986-id-3 ...
- 【C++】拷贝构造函数(深拷贝,浅拷贝)详解
一.什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: ; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量. 下面看一个类对 ...
- c++中拷贝构造函数,浅拷贝和深拷贝的区别
在C++提供了一种特殊的构造函数,称为拷贝构造函数.拷贝构造函数具有一般构造函数的所有特性,其作用是使用一个已经存在的对象(由拷贝构造函数的参数指定的对象)去初始化一个新的同类对象,即完成本类对象的复 ...
- 拷贝构造函数(深拷贝vs浅拷贝)
拷贝构造函数(深拷贝vs浅拷贝) 类对象之间的初始化是由类的拷贝构造函数完毕的.它是一种特殊的构造函数,它的作用是用一个已知的对象来初始化还有一个对象.假设在类中没有显式地声明一个拷贝构造函数.那么, ...
- 【C++札记】拷贝构造函数,浅拷贝和深拷贝
一:拷贝构造函数 拷贝构造函数是一种特殊的构造函数,遵循如下的规则: 1.函数名和类名一致,没有返回值. 2.必须有一个参数,参数是本类型的一个引用变量. 3.拷贝构造函数可以访问参数对象的任意成员( ...
- C++拷贝构造函数(深拷贝,浅拷贝)
http://www.cnblogs.com/BlueTzar/articles/1223313.html 对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; ...
- c++拷贝构造函数(深拷贝,浅拷贝)详解
一.什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: ; int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量. 下面 ...
- c++拷贝构造函数(深拷贝、浅拷贝)——转
拷贝构造函数: 拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类的一个引用变量,该参数是const类型,不可变的.例如:类A的拷贝构造函数的形式为A(A& ...
- C++拷贝构造函数:浅拷贝与深拷贝
在介绍C++浅拷贝与深拷贝之前,我们先引出C++的拷贝构造函数. C++拷贝构造函数是一种特殊的构造函数,其形参是本类对象的引用.用于在建立一个新的对象时,使用一个已经存在的对象来初始化这个新对象.因 ...
随机推荐
- Kubernetes的负载均衡问题(Nginx Ingress)
nginx 反向代理 https://www.cnblogs.com/ericnie/p/6965091.html Kubernetes 集群中使用 Traefik https://blog.csdn ...
- 微信小程序:下拉刷新
下拉刷新 1.需要在json文件中,设置"enablePullDownRefresh": true,表示该页面使用下拉刷新 2.在微信内置函数onPullDownRefresh中进 ...
- Python中字符串的操作
字符串的基本详情 用单引号或者双引号包含的内容 不支持直接在内存中修改 可支持索引.切片.成员检查.长度查看 字符串赋值到变量 str1 = 'hello world' 字符串打印查看 str1 = ...
- 解决ubuntu中arm-linux-gcc not found
1. 注意检查是不是 换了bash的原因 2. 此外还有权限切换以后环境变量换了 3.如果遇到环境变量配置以后,能够找到版本(也就是说 输入 命令的开头按tab以后能够出现补全),这是因为64位下运行 ...
- Canvas判断内容为空
如题,项目需要做一个canvas的绘图工具,绘制图纸传递给后台.因此需要做一个非空验证,记录解决方法祝大家早日脱坑. js验证代码: //验证canvas画布是否为空函数function isCanv ...
- Chrome DevTools: Color tricks in the Elements Panel
shift + click to change the color format Tip one The Colour Platters are customeised for you .they s ...
- 原生JavaScript运动功能系列(三):多物体多值运动
多物体同时出发运动函数实现 多属性同步运动变化实现 一.多物同时触发运动函数实现 前面两个动画示例基本理解了动画的核心:位置变化和速度变化,操作的核心就是定时器分段叠加属性值.但是动画还是基于单个元素 ...
- std::rotate使用
1. 进行元素范围上的左旋转 first - 原范围的起始 n_first - 应出现在旋转后范围起始的元素 last - 原范围的结尾 原来:1 2 3 左旋转后(起始元素是2) : 2 3 1
- [Android] Android 使用 Greendao 操作 db sqlite(1)-- 直接在MainActivity中调用
继续接上文: Android 使用 Greendao 操作 db sqlite 布局文件: activity_test_green.xml <?xml version="1.0&quo ...
- 【由浅入深理解java集合】(三)——集合 List
第一篇文章中介绍了List集合的一些通用知识.本篇文章将集中介绍List集合相比Collection接口增加的一些重要功能以及List集合的两个重要子类ArrayList及LinkedList. 一. ...