C 急速深度拷貝

2021-10-03 04:16:30 字數 2852 閱讀 8882

怎樣深度拷貝最快呢?

假設有這樣的倆個物件

public class people

public string name

public string ***

}

public class man

public int age

public string name

public string ***

}

如果我們將people的所有屬性都賦值給man。如果數量不多,我們乙個個手寫就好了,但是假設物件屬性有成百上千個怎麼辦???乙個個手寫?那還不累死!

一般情況下有倆種辦法

第一種,反射,逐個複製,但是我們都知道,反射是很慢的。效能並不好;

第二種,通過jsonconverter.序列化再反序列化,(⊙o⊙)…。效能比反射還差。

那有什麼更好的辦法嗎???

第一種 通過位元組緩衝。將成員資訊緩衝到字典裡面去,讀取的時候再去裡面查詢。但是我們知道,字典是比較耗費時間的。

第二種 泛型緩衝,啥叫泛型緩衝?其實在c#裡面 例如類 list在編譯之後和 list還有關係嗎? 其實編譯器是將其編譯成為了倆單獨的類。如果我們將我們的資料 存在類裡面那麼效能便是最高最快的。

廢話說多了,貼**。

_";if (!keyvaluepairs.containskey(key))

return ((func)keyvaluepairs[key]).invoke(tin);

}/// /// 複製資訊

///

///

/// 物件成員列表

/// 成員繫結表

/// 表示式引數

private static void copy(ienumerablememberinfos, listmemberbindings, parameterexpression parameter)

var gg = propertys.getproperty(item.name);

if (gg == null)

var property = expression.property(parameter, gg);

var member = expression.bind(item, property);

memberbindings.add(member);}}

}上面的**是幹啥的?核心就是動態生成linq語句。逐個將屬性讀取出來,然後逐個編寫linq 屬性賦值語句,最後新建初始化tout。

我們知道 在字典裡查詢資料時其實是通過傳入key的雜湊值查詢的,速度還是比較慢的。我們再次優化

private static funcfunc = null;

/// /// 深度複製

///

///

///

public static tout copy(tin tin) => func.invoke(tin);

/// /// 複製資訊

///

///

/// 物件成員列表

/// 成員繫結表

/// 表示式引數

private static void copy(ienumerablememberinfos, listmemberbindings, parameterexpression parameter)

var gg = propertys.getproperty(item.name);

if (gg == null)

var property = expression.property(parameter, gg);

var member = expression.bind(item, property);

memberbindings.add(member);}}

}公升級後一對tin和tout對應乙個新的類。如此相當於我們直接操作類了,效能槓槓的。

呼叫就簡單了。非常簡單。如下 

var peop = new people() ;
第一次呼叫泛型緩衝時,我們會呼叫其靜態構造器,並生成其靜態賦值委託。第二次呼叫時由於 靜態構造器只呼叫一次,我們就直接呼叫其泛型委託了,啊哈,一下就賦值完成。

經過100萬次賦值測試,泛型委託深拷貝方式 是 原生硬編碼的倆倍。快不快?字典形式深拷貝是原生硬碼方式的10倍。反射和序列化方式是原生硬編碼的100多倍。

最後我們將上面的**優化掉,乙個擴充套件方法使用起來可就美滋滋了

/// /// 轉殖擴充套件

///

public static class cloneextension

_";if (!keyvaluepairs.containskey(key))

return ((func)keyvaluepairs[key]).invoke(tin);

}/// /// 複製資訊

///

///

/// 物件成員列表

/// 成員繫結表

/// 表示式引數

private static void copy(ienumerablememberinfos, listmemberbindings, parameterexpression parameter)

var gg = propertys.getproperty(item.name);

if (gg == null)

var property = expression.property(parameter, gg);

var member = expression.bind(item, property);

memberbindings.add(member);}}

}

C 預設拷貝建構函式 深度拷貝和淺拷貝

c 類的中有兩個特殊的建構函式,1 無參建構函式,2 拷貝建構函式。它們的特殊之處在於 1 當類中沒有定義任何建構函式時,編譯器會預設提供乙個無參建構函式且其函式體為空 2 當類中沒有定義拷貝建構函式時,編譯器會預設提供乙個拷貝建構函式,進行成員變數之間的拷貝。這個拷貝操作是淺拷貝 這裡只講拷貝建構...

深度拷貝和潛拷貝

淺 復 制 在複製操作時,對於被複製的物件的每一層複製都是指標複製。深 復 制 在複製操作時,對於被複製的物件至少有一層複製是物件複製。完全複製 在複製操作時,對於被複製的物件的每一層複製都是物件複製。注 1 在複製操作時,對於物件有n層是物件複製,我們可稱作n級深複製,此處n應大於等於1。2 對於...

C deep copy 深度拷貝

當類的成員變數存在指標型別時,如果採用賦值語句將乙個該類物件賦給另外乙個物件時,缺省會採用淺拷貝,也即兩個指標型別的成員變數指向同乙個位址,這樣當物件生命週期結束時會呼叫析構函式,釋放相應的記憶體位址。但是由於淺拷貝,會導致釋放發生兩次,如此第二次釋放發生時,因為已經被釋放過一次,所以程式會奔潰。如...