C 賦值 淺拷貝 深拷貝和零拷貝解析

2021-10-23 17:50:56 字數 2201 閱讀 4160

1. 淺拷貝

淺拷貝只複製指向某個物件的指標,而不複製物件本身,新舊物件還是共享同一塊記憶體。

2. 深拷貝

深拷貝會另外創造乙個一模一樣的物件,新物件跟原物件不共享記憶體,修改新物件不會改到原物件。

深拷貝和淺拷貝是只針對object和array這樣的引用資料型別的,示意圖大致如下:

3. 賦值與淺拷貝差異

賦值:把乙個物件賦值給乙個新的變數時,賦的其實是該物件的在棧中的位址,而不是堆中的資料。也就是兩個物件指向的是同乙個儲存空間,無論哪個物件發生改變,其實都是改變的儲存空間的內容,因此,兩個物件是聯動的。

淺拷貝:

淺拷貝是按位拷貝物件,它會建立乙個新物件,這個物件有著原始物件屬性值的乙份精確拷貝。如果屬性是基本型別,拷貝的就是基本型別的值;如果屬性是記憶體位址(引用型別),拷貝的就是記憶體位址 ,因此如果其中乙個物件改變了這個位址,就會影響到另乙個物件。即預設拷貝建構函式只是對物件進行淺拷貝複製(逐個成員依次拷貝),即只複製物件空間而不複製資源。

對比賦值與淺拷貝會對原物件帶來哪些改變:

物件賦值操作:

// 物件賦值

var obj1 =

;var obj2 = obj1;

obj2.name =

"lisi"

;obj2.language[1]

=["二",

"三"]

;console.

log(

'obj1'

,obj1)

console.

log(

'obj2'

,obj2)

物件賦值後結果如下:

淺拷貝操作:

// 淺拷貝

var obj1 =

;var obj3 =

shallowcopy

(obj1)

;obj3.name =

"lisi"

;obj3.language[1]

=["二",

"三"]

;function shallowcopy

(src)

;for

(var prop in src)

}return dst;

}console.

log(

'obj1'

,obj1)

console.

log(

'obj3'

,obj3)

淺拷貝操作結果:

上面例子中,obj1是原始資料,obj2是賦值操作得到,而obj3淺拷貝得到。我們可以很清晰看到對原始資料的影響,具體請看下表:

4. linux中的零拷貝

在 linux 中,減少拷貝次數的一種方法是呼叫 mmap() 來代替呼叫 read.

首先,應用程式呼叫了 mmap() 之後,資料會先通過 dma 被複製到作業系統核心的緩衝區中去。接著,應用程式跟作業系統共享這個緩衝區,這樣,作業系統核心和應用程式儲存空間就不需要再進行任何的資料複製操作。應用程式呼叫了 write() 之後,作業系統核心將資料從原來的核心緩衝區中複製到與 socket 相關的核心緩衝區中。接下來,資料從核心 socket 緩衝區複製到協議引擎中去,這是第三次資料拷貝操作。

通過使用 mmap() 來代替 read(), 已經可以減半作業系統需要進行資料拷貝的次數。當大量資料需要傳輸的時候,這樣做就會有乙個比較好的效率。但是,這種改進也是需要代價的,使用 mma()p 其實是存在潛在的問題的。當對檔案進行了記憶體對映,然後呼叫 write() 系統呼叫,如果此時其他的程序截斷了這個檔案,那麼 write() 系統呼叫將會被匯流排錯誤訊號 sigbus 中斷,因為此時正在執行的是乙個錯誤的儲存訪問。

淺拷貝 深拷貝和淺賦值 深賦值

include includeusing namespace std class string else 淺拷貝 也就是系統預設的拷貝,可寫可不寫。string const string s 預設的拷貝構造 深拷貝 string const string s string s2 s1 深賦值 str...

賦值 淺拷貝和深拷貝

三種方法的形式存在一定的類似,但是也存在各個之間不相同的地方。淺拷貝和深拷貝是用在物件 object 或者陣列 array 這樣的資料型別拷貝賦值時候的說法,而賦值操作也可以用在基礎的資料型別,如number string等 賦值 對於物件型別資料的影響 賦於該值在棧中的位址,而不是堆中的資料,使得...

賦值 淺拷貝 深拷貝

堆是動態分配記憶體,記憶體大小不一 棧是自動分配相對固定大小的記憶體空間,並由系統自動釋放 基本資料型別值是不可變的,比較是值的比較 基本資料型別,傳值。開闢乙個新的記憶體空間 js 基本資料型別,儲存在 棧 中,記憶體可以及時 引用型別值是可變的,比較是引用的比較,看其引用是否指向同乙個物件 引用...