標簽:com http class blog style code div img tar ext art
對于普通類型的對象來說,它們之間的複制是很簡單的,例如:
int a=88;
int b=a;
而類對象與普通對象不同,類對象內部結構一般較爲複雜,存在各種成員變量。下面看一個類對象拷貝的簡單例子。
運行程序,屏幕輸出100。從以上代碼的運行結果可以看出,系統爲對象B分配了內存並完成了與對象A的複制過程。就類對象而言,相同類型的類對象是通過拷貝構造函數來完成整個複制過程的。下面舉例說明拷貝構造函數的工作過程。
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++拷貝構造函數(深拷貝,淺拷貝),布布扣,bubuko.com
標簽:com http class blog style code div img tar ext art
原文地址:http://www.cnblogs.com/kuoyan/p/3694549.html