C++淺拷貝的另一種實現方式以及CONST指針

C++的淺拷貝,雖然編譯器已經默認幫我們實現了,但是作爲一個技術人員應該要具備有最基本的“黑客精神”,說到C++淺拷貝的實現,大家第一反應就是通過拷貝構造函數實現成員變量的直接賦值。也就是如下的代碼:

  class A
 {
 public:
	A()
	{
	  arrayA = new int [size];//內存分配
	   for( size_t i = 0;i<size;i++)
	{
	   arrayA[i] = i;
	 }
~A()
{
delete arrayA;
}
 A(const A& object)//複製構造函數
 {
  this->arrayA = object.arrayA;//成員變量直接複製,實現淺拷貝
 }	
private:
const size_t size= 40;
int *arrayA;
}

當然寫到這裏,如果就是這麼簡單的話就沒有必要寫這篇博客了,淺拷貝也叫按位拷貝,就是將一個對象的內存空間的內容遠遠本本拷貝過去。多說一點因爲對象的指針成員所指向的內存不屬於該對象的內容,不佔用對象的內存空間,所以淺拷貝不會將對象中指針成員所指向的內存複製過去;就好像上面的例子如果執行淺拷貝,那麼拷貝的只是arrayA本身,而它所指向的40個整形的內存空間是不會被拷貝過去的;因此淺拷貝的源對象如果被析構之後,複製對象的中的指針成員就會成爲空懸指針(Dangling Pointer)
扯遠了,那按位拷貝從語義上來說就是,在內存空間中以byte爲單位將內存複製到另一個內存空間。所以要怎麼實現呢,那我們可以參考字符串拷貝,知道源內存首地址,知道內存空間大小,知道目標內存地址就可以連續地拷貝過去了。參照下列代碼:

class A
 {
 public:
	A()
	{
	  arrayA = new int [size];//內存分配
	   for( size_t i = 0;i<size;i++)
	{
	   arrayA[i] = i;
	 }
~A()
{
delete arrayA;
}
 A(const A& object)//複製構造函數
 {
  char* source = &object; //得到目標地址,賦值給char指針目的是爲了在指針運算時讓系統按1個字節去遞增
  char* dest  = (char*)this; 
 /*獲取目標地址,也就是本對象的地址,注意this指針是一個常量,且是一個非左值不能被賦值和修改,只能讀取,所以要修改本對象的內容,只能通過獲取本對象的地址,並將內容拷貝到本對象的地址中*/

for(size_t i = 0; i<sizeof(A);i++)
     *(dest+i) = *(source+i);//內存拷貝,完成從源對象到目標對象的內存複製。
 }	
private:
const size_t size= 40;
int *arrayA;

}

上面的版本爲了看清楚明白其中的原理再簡化的版本

A(const A &object)
{
  memcpy(this, &object,sizeof(A)); //呵呵就是這麼簡單
}

再扯一波,剛剛說到const指針this, const指針通常指的是指針本身不能被修改,但是其指向的內容可以被修改,this就是這種類型。還有一種是指向const內容的指針,這種這種指針本身可以被修改,但是其指向的內容不可以被修改。
具體的聲明如下例如:
第一種:

const int *p = new int(10);//const在指針的左邊,聲明一個指針指向const int。
*p = 20;//錯誤,const內容不能被修改
p++//正確,指針不是const

第二種:

int * const p = new int(10);//const在指針的右邊,聲明一個const指針指向int。
*p = 20;//正確,內容不是const
p++//錯誤,指針是const
const int* const p;//內容和指針都是const都不能被修改 

對於第一種如果我們要修改const內容該怎麼辦,那就是用const_cast<>(data)來去掉const屬性

const int *p = new int(10);//const在指針的左邊,聲明一個指針指向const int。
*p = 20;//錯誤,const內容不能被修改
int *unconst_p = const_cast<int*>(p);
*unconst_p = 20;//去掉const屬性之後正確
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章