php淺複製與深複製,js淺複製和深複製

本文目錄一覽:

淺複製和深複製的區別?

淺層複製:只複製指向對象的指針,而不複製引用對象本身。

深層複製:複製引用對象本身。

編程裡面的深拷貝和淺拷貝各是什麼意思,怎麼理解這兩個?

1、淺拷貝:默認的拷貝就是淺拷貝。 僅僅多了個指針指向原來的空間。

2、深拷貝:自己寫的拷貝,自己申請了動態內存空間,用了new 或 malloc 。不但多了指針,而且多了空間。

3、用深拷貝的話,最好用自己寫的析構,記得在裡面釋放內存,也可以用默認析構。

4.用淺拷貝(即默認隱藏的拷貝),最好用默認析構,若用自己寫的析構裡面 ,記得不要釋放內存,不然會造成重複釋放內存而報錯。

什麼是深拷貝和淺拷貝

淺拷貝就是指對象複製的時候只複製一層;深拷貝是指複製對象的所有層級。

深拷貝和淺拷貝,主要是對象發生複製的時候,根據複製的層級不同來區分的。很多人在這裡經常變量賦值發生混淆。對於JavaScript數組等複雜的數據類型來說,將其賦值給其它變量,其實只是複製了對象的地址給它,兩個變量指向的是同一個對象,因此普通的賦值既不是深拷貝也不是淺拷貝。

深拷貝和淺拷貝需要注意的地方就是可變元素的拷貝:

在淺拷貝時,拷貝出來的新對象的地址和原對象是不一樣的,但是新對象裡面的可變元素(如列表)的地址和原對象里的可變元素的地址是相同的,也就是說淺拷貝它拷貝的是淺層次的數據結構(不可變元素),對象里的可變元素作為深層次的數據結構並沒有被拷貝到新地址裡面去。

而是和原對象里的可變元素指向同一個地址,所以在新對象或原對象里對這個可變元素做修改時,兩個對象是同時改變的,但是深拷貝不會這樣,這個是淺拷貝相對於深拷貝最根本的區別。

淺拷貝與深拷貝的區別

數據分為基本數據類型(String, Number, Boolean, Null, Undefined,Symbol)和對象數據類型。

基本數據類型的特點:直接存儲在棧(stack)中的數據。

引用數據類型的特點:存儲的是該對象在棧中引用,真實的數據存放在堆內存里。

引用數據類型在棧中存儲了指針,該指針指向堆中該實體的起始地址。當解釋器尋找引用值時,會首先檢索其在棧中的地址,取得地址後從堆中獲得實體。

深拷貝和淺拷貝是只針對Object和Array這樣的引用數據類型的。

深拷貝和淺拷貝的示意圖大致如下:

淺拷貝只複製指向某個對象的指針,而不複製對象本身,新舊對象還是共享同一塊內存。但深拷貝會另外創造一個一模一樣的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象。

當我們把一個對象賦值給一個新的變量時,賦的其實是該對象的在棧中的地址,而不是堆中的數據。也就是兩個對象指向的是同一個存儲空間,無論哪個對象發生改變,其實都是改變的存儲空間的內容,因此,兩個對象是聯動的。

淺拷貝是按位拷貝對象,它會創建一個新對象,這個對象有着原始對象屬性值的一份精確拷貝。如果屬性是基本類型,拷貝的就是基本類型的值;如果屬性是內存地址(引用類型),拷貝的就是內存地址 ,因此如果其中一個對象改變了這個地址,就會影響到另一個對象。即默認拷貝構造函數只是對對象進行淺拷貝複製(逐個成員依次拷貝),即只複製對象空間而不複製資源。

我們先來看兩個例子,對比賦值與淺拷貝會對原對象帶來哪些改變?

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

Object.assign() 方法可以把任意多個的源對象自身的可枚舉屬性拷貝給目標對象,然後返回目標對象。但是 Object.assign()進行的是淺拷貝,拷貝的是對象的屬性的引用,而不是對象本身。

修改新對象會改到原對象:

同樣修改新對象會改到原對象:

原數組的元素會按照下述規則拷貝:

如果該元素是個對象引用(不是實際的對象),slice 會拷貝這個對象引用到新的數組裡。兩個對象引用都引用了同一個對象。如果被引用的對象發生改變,則新的和原來的數組中的這個元素也會發生改變。

對於字符串、數字及布爾值來說(不是 String、Number 或者 Boolean 對象),slice 會拷貝這些值到新的數組裡。在別的數組裡修改這些字符串或數字或是布爾值,將不會影響另一個數組。

可能這段話晦澀難懂,我們舉個例子,將上面的例子小作修改:

這種方法雖然可以實現數組或對象深拷貝,但不能處理函數。

這是因為JSON.stringify() 方法是將一個JavaScript值(對象或者數組)轉換為一個 JSON字符串,不能接受函數。

該函數庫也有提供_.cloneDeep用來做 Deep Copy。

PHP對象的淺複製與深複製的實例詳解

PHP對象的淺複製與深複製的實例詳解

最近在看原型模式時注意到這個問題~~PHP中對象

‘=’

與‘clone’的區別

實例代碼:

//聚合類

class

ObjA

{

public

$num

=

0;

public

$objB;//包含的對象

function

__construct()

{

$this-objB

=

new

ObjB();

}

//只有實現了下面方法聚合類

才能實現深複製

/*function

__clone()

{

$this-objB

=

clone

$this-objB;

}*/

}

class

ObjB

{

public

$num2

=

0;

}

//原型對象

$objA

=

new

ObjA();

//複製對象(‘=’複製引用)

$objA2

=

$objA;

$objA2-num

=

2;

//隨着$objA2-num的變化

$objA-num也變化了

print_r($objA-num.’br/’);//結果為2

print_r($objA2-num.’br/’);//結果為2

//複製對象(‘clone’關鍵字克隆)

$objA3

=

clone

$objA;

$objA3-num

=

4;

//隨着$objA3-num的變化

$objA-num沒有變化

print_r($objA-num.’br/’);//結果為2

print_r($objA3-num.’br/’);//結果為4

//但是clone的對象(是聚合類)中包含其他對象時所包含的對象(objB)複製的是引用

$objA3-objB-num2

=

7;

print_r($objA3-objB-num2.’br/’);//結果是7

print_r($objA-objB-num2.’br/’);//結果是7/pre

如有疑問請留言或者到本站社區交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

深複製(Deep Copy)、淺複製(Shallow Copy)、copy、mutableCopy

1.屬性中copy與strong特性的區別

copy:

創建一個對象的副本,在創建的那一刻新對象與原始對象內容相同。

新的對象引用計數為1,與原始對象引用計數無關,且原始對象引用計數不會改變。

使用copy創建的新對象也是 強引用 ,使用完成後需要負責釋放該對象。

copy特性可以減少對象對上下文的依賴。新對象、原始對象中任一對象的值改變不會影響另一對象的值。

要想設置該對象的特性為copy,該對象必須遵守NSCopying協議,Foundation類默認實現了NSCopying協議,所以只需要為自定義的類實現該協議即可。

strong:

創建一個強引用的指針,引用對象引用計數加1。

strong特性表示兩個對象內存地址相同(建立一個指針,進行指針拷貝),內容會一直保持相同,直到更改一方內存地址,或將其設置為nil。

如果有多個對象同時引用一個屬性,任一對象對該屬性的修改都會影響其他對象獲取的值。

2.淺複製與深複製

對象的拷貝有淺複製和深複製兩種方式。淺複製只複製指向對象的指針,並不複製對象本身;深複製是直接複製整個對象到另一塊內存中。即淺複製是複製指針,深複製是複製內容。

NSObject提供了copy和mutableCopy 方法,copy複製後對象是不可變對象(immutable),mutableCopy複製後的對象是可變對象(mutable),與原始對象是否可變無關。

深拷貝和淺拷貝最根本的區別:是否真正獲取一個 對象的複製實體 ,而不是引用。

淺拷貝:修改堆內存中的同一個值。 

深拷貝:修改堆內存中的不同的值。

2.1非集合類對象的copy與mutableCopy

非集合類對象指的是NSString、NSNumber之類的對象,深複製會複製引用對象的內容,而淺複製只複製引用這些對象的指針。因此,如果對象A被淺複製到對象B,對象B和對象A引用的是同一內存地址的實例變量或屬性。

2.1.1不可變對象的copy與mutableCopy

2.1.2可變對象的copy與mutableCopy

2.2容器類對象的深複製、淺複製

容器類對象指NSArray、NSDictionary等。

對於容器類,需要探討的是複製後容器內元素的變化,而非容器本身內存地址是否發生了變化。

2.2.1容器類對象的淺複製

當對集合進行淺複製時,將複製原始集合中元素指針到新的集合,即原始集合中元素引用計數加一。

2.2.2容器類對象的深複製

有兩種方式對容器類對象進行深複製:

一:使用initWithArray: copyItems:類型方法,其中,第二個參數為YES。

二:使用歸檔、解檔。

2.3自定義對象的深複製、淺複製

3.修改指針指向

總結:

淺拷貝儘可能少的複製對象,集合的淺拷貝副本只是集合結構的副本,而不是集合內元素的副本。淺拷貝獲得的副本與原始集合共享各個元素。

深拷貝複製一切內容。集合的深拷貝會複製集合的結構和元素,但如果集合內元素也是集合,則涉及到一層深拷貝、完全深拷貝。

參考:

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/189438.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-11-29 08:03
下一篇 2024-11-29 08:03

相關推薦

  • JS Proxy(array)用法介紹

    JS Proxy(array)可以說是ES6中非常重要的一個特性,它可以代理一個數組,監聽數據變化並進行攔截、處理。在實際開發中,使用Proxy(array)可以方便地實現數據的監…

    編程 2025-04-29
  • PHP和Python哪個好找工作?

    PHP和Python都是非常流行的編程語言,它們被廣泛應用於不同領域的開發中。但是,在考慮擇業方向的時候,很多人都會有一個問題:PHP和Python哪個好找工作?這篇文章將從多個方…

    編程 2025-04-29
  • PHP怎麼接幣

    想要在自己的網站或應用中接受比特幣等加密貨幣的支付,就需要對該加密貨幣擁有一定的了解,並使用對應的API進行開發。本文將從多個方面詳細闡述如何使用PHP接受加密貨幣的支付。 一、環…

    編程 2025-04-29
  • 解析js base64並轉成unit

    本文將從多個方面詳細介紹js中如何解析base64編碼並轉成unit格式。 一、base64編碼解析 在JavaScript中解析base64編碼可以使用atob()函數,它會將b…

    編程 2025-04-29
  • Node.js使用Body-Parser處理HTTP POST請求時,特殊字符無法返回的解決方法

    本文將解決Node.js使用Body-Parser處理HTTP POST請求時,特殊字符無法返回的問題。同時,給出一些相關示例代碼,以幫助讀者更好的理解並處理這個問題。 一、問題解…

    編程 2025-04-29
  • t3.js:一個全能的JavaScript動態文本替換工具

    t3.js是一個非常流行的JavaScript動態文本替換工具,它是一個輕量級庫,能夠很容易地實現文本內容的遞增、遞減、替換、切換以及其他各種操作。在本文中,我們將從多個方面探討t…

    編程 2025-04-28
  • 使用PHP foreach遍歷有相同屬性的值

    本篇文章將介紹如何使用PHP foreach遍歷具有相同屬性的值,並給出相應的代碼示例。 一、基礎概念 在講解如何使用PHP foreach遍歷有相同屬性的值之前,我們需要先了解幾…

    編程 2025-04-28
  • JS圖片沿着SVG路徑移動實現方法

    本文將為大家詳細介紹如何使用JS實現圖片沿着SVG路徑移動的效果,包括路徑製作、路徑效果、以及實現代碼等內容。 一、路徑製作 路徑的製作,我們需要使用到SVG,SVG是可縮放矢量圖…

    編程 2025-04-27
  • PHP獲取301跳轉後的地址

    本文將為大家介紹如何使用PHP獲取301跳轉後的地址。301重定向是什麼呢?當我們訪問一個網頁A,但是它已經被遷移到了另一個地址B,此時若服務器端做了301重定向,那麼你的瀏覽器在…

    編程 2025-04-27
  • 如何使用JS調用Python腳本

    本文將詳細介紹通過JS調用Python腳本的方法,包括使用Node.js、Python shell、child_process等三種方法,以及在Web應用中的應用。 一、使用Nod…

    編程 2025-04-27

發表回復

登錄後才能評論