您的位置:首页 > 编程语言 > C语言/C++

【C++】深拷贝和浅拷贝解析

2016-04-04 20:45 375 查看
前言:

    最近在做C++二级题的时候总是会遇到深拷贝,想想最先接触这个词的时候是在大话设计模式中,但是C++中的深拷贝和C#中的略有区别,今天先来介绍一下C++中的深拷贝吧!

   简单的说:深拷贝的时候,相同数据指针指向不同的内存地址

              浅拷贝的时候,指针指向相同的内存地址

 
现在来深入探讨一下:

     浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间,浅拷贝只是对对象的简单拷贝,让几个对象共用一片内存,当内存销毁的时候,指向这片内存的几个指针需要重新定义才可以使用,要不然会成为野指针。

<span style="font-family:KaiTi_GB2312;font-size:18px;">#include <iostream>
#include <cstring>
using namespace std;
class Test
{
private:
int a;
char *str;
public:
Test(int b, char *s)
{
a=b;
strcpy(str,s); //肇事地点,但不是祸端
}
Test(const Test& C)
{
a=C.a;
strcpy(str,C.str);
}
void show ()
{
cout<<a<<","<<str<<endl;
}
};

int main()
{
Test a(100,"hello");
Test b(a);
a.show();
b.show();
return 0;
}</span>

   从上面的程序我们可以知道,对象a的数据成员a获得实际参数100的值,而数据成员str,即指针,是个随机地址值(指针的值,非指针指向的值)!在程序中,试图通过strcpy(str,s);将形式参数s指向的字符串"hello",复制到str所指向的那个位置,而那个位置,其地址并不是经过系统分配来的,这是个危险的操作。在这里,str这样未经过分配的地址(指针),被称为“野指针”。
  那么如何解决这个问题呢?

就是在构造函数中,要为指针类型的成员,分配专门的空间。以这条规则构建的复制,称作为深复制!深拷贝是指拷贝对象的具体内容,而内存地址是自主分配的,拷贝结束之后,两个对象虽然存的值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉。

 把上面的程序中改写一下完成深复制

<span style="font-family:KaiTi_GB2312;font-size:18px;">#include<iostream>
using namespace std;
class A
{
private:
int *arrayAddr;//保存一个有len个整型元素的数组的首地址
int len; //记录动态数组的长度
public:
A(int *a, int n);
~A();
int sum();
};
A::A(int *a, int n)
{
len=n;
arrayAddr=new int
; //为指针数据成员分配空间,注意,没有上面例子中加1那回事
for(int i=0; i<n; i++) //逐个地将a指向的值逐个地复制过来
{
arrayAddr[i]=a[i];
}
}
//析构函数的类外定义,释放指针型数据a所指向的空间
A::~A()
{
delete [] arrayAddr;
}
int A::sum() //获得a指向的数组中下标为i的元素的值
{
int s=0;
for(int i=0; i<len; i++) //逐个地将a指向的值逐个地复制过来
{
s+=arrayAddr[i];
}
return s;
}

int main(){
int b[10]= {75, 99, 90, 93, 38, 15, 5, 7, 52, 4};
A r1(b,10);
cout<<"和:"<<r1.sum()<<endl;
int c[15] = {18,68,10,52,3,19,12,100,56,96,95,97,1,4,93};
A r2(c,15);
cout<<"和:"<<r2.sum()<<endl;
return 0;
} </span>

如果不想看上面的内容,可以看最后总结。很经典的啊。
(1)什么时候用到拷贝函数?

  a.一个对象以值传递的方式传入函数体; 

  b.一个对象以值传递的方式从函数返回;

  c.一个对象需要通过另外一个对象进行初始化。

如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝
(2)什么叫深拷贝?什么是浅拷贝?两者异同?

深如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。 
(3)深拷贝好还是浅拷贝好?
    如果实行浅拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。

 小结

不怕不知道就怕不知道,虽然之前学过C#中的深拷贝,但是和C++中的还是有区别的,通过总结让知识更有力量。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: