未來的C 之唯讀引用與結構體

2021-09-17 06:09:08 字數 2422 閱讀 6424

c++中提供了const特性,使用該特性定義的引數,其所引用的引數或物件將不會被呼叫函式修改(當然const還提供了更多的特性,參見「const正確性」)。在新的建議中,c#也將提供類似的特性。

\\唯讀ref引數

\\ 在c#中,「唯讀引用」也可稱為「in引數」,兩者提供了類似的限制。唯讀引用的基本思想是,如果用「readonly ref」或僅是「in」標註乙個引數,那麼編譯器會解釋為「將該引數按引用傳遞以改進效能,但不允許實際更改該引數」。該特性對於在高效能場景下的大型結構體尤為有用。在建議中引用了如下的例子:

\\

\

我們知道,在xna等圖形庫中的向量/矩陣數**算符是具有ref操作符的,這純粹是出於效能上的考慮。roslyn編譯器本身就有**使用了結構體,以避免記憶體分配,並可通過引用的方式傳遞結構體,免除複製的繁瑣。

\

\\

該語法還結合了c++版本的const。即引數本身是不可更改的,引數所引用的物件或結構體中的所有資料也是不可更改的。

\\ 當前在通過引用傳遞乙個引數時,必須使用「ref」或「out」關鍵字。在這個建議實現後,使用「in」引數無需受此限制。進而表示式的結果也可以傳遞進來(當前這在vb中是允許的,但是在c#中尚不允許)。

\\實現細節

\\ 對比「ref」和「out」引數,它們的過載規則具有相同的工作機制。

\\ 這依然有待議定,但是當前的計畫是不允許「in」引數被匿名函式或async函式捕獲(即生成乙個閉包物件)。捕獲「in」引數的問題在於會導致一次拷貝,這破壞了使用「in」引數的初衷,即避免拷貝所導致的效能損耗。

\\ 將引數標為「readonly ref」或「in」,並不會令引用值成為不可變值。雖然引數值無法被宣告函式更改,但可以在其它地方修改。無需使用多執行緒,只需能訪問引數所引用原始變數的方法即可。

\\ 在結構體上呼叫方法可能會導致問題。在建議中是這樣說的:

\\

\

結構體的所有常規例項方法可轉變(mutate)例項,或是對例項暴露引用(ref-expose),因此必須要建立乙個臨時拷貝,正如當前對接收者是唯讀域時的做法。

\\ 但是,由於沒有考慮向後相容,也不存在變通方案,所以編譯器只是給出乙個警告,以確保使用者留意到這一隱式拷貝。

\

\\

使用「out」引數時,乙個特殊的引數標識了是否需要「in」引數。該引數將被舊的編譯器忽略,因此沒有向後相容的問題。

\\唯讀ref返回

\\ 與該特性密切相關的是將ref returns標為唯讀的功能。開發人員使用「in」引數,主要因為它能提供良好的效能,但是「in」引數不允許返回表示式的結果。返回值必須是正常ref返回的乙個合法變數,其中可以包含陣列元素、ref引數和物件中的域。

\\ref/in的擴充套件方法

\\ 「ref」擴充套件方法將允許擴充套件方法修改傳遞進來的結構體。需要編譯器能驗證傳遞給ref擴充套件方法的引數是可變的。

\\ 雖然「in」擴充套件方法不允許修改引數,但對於效能敏感的**依然十分有用,尤其是結構體非常大的時候。這時當然不需要乙個可變引數。

\\ 在上面兩種情況下,該特性只能用於結構體。

\\ 編輯按:假定廣泛使用了pureattribute,編譯器將不允許對「in」擴充套件方法呼叫非pureattribute的方法。但由於對效能並無太大改善,因此不大可能廣泛應用。

\\唯讀結構體

\\ 將結構體變數標為readonly可能會對效能產生影響。編譯器無法確定某個呼叫是否會對結構體產生改動,因此會預設能夠修改,並始終複製唯讀結構體變數的副本。

\\ 使用該特性,開發人員可以在型別層面上將整個結構體標為唯讀。這樣一來,編譯器就知道:在通過唯讀結構體的變數暴露該唯讀結構體時,不需要進行拷貝。

\\ 在建議中指出:

\\

\

唯一乙個顯而易見的問題在於:是否需要將其中一些方法改為賦值(mutator)方法。

\\ 目前,對唯讀結構體進行逐個控制只會增加不必要的複雜性,我們可以後期需要時再行新增。

\\ 當前,我們假定可變和不可變成員「混合」的結構體並不常見。此外,可變結構體的部分變數通常需要是lvalues,從而避免隱式拷貝的影響。

\

\\

缺點

\\ 建議還指出,這些功能對已有**不大可能有幫助,但在如下新場景中會很有用,例如:\\

在建議中也提出了警告,在「in」引數上的限制可迴圈作用於被呼叫函式。但這一問題並不嚴重,因為已經可以使用「out」引數執行同一操作了。

\\檢視英文原文:c# futures: read-only references and structs

\\ 感謝孫薇對本文的審校。

\

未來的C 之唯讀引用與結構體

c 中提供了const特性,使用該特性定義的引數,其所引用的引數或物件將不會被呼叫函式修改 當然const還提供了更多的特性,參見 const正確性 在新的建議中,c 也將提供類似的特性。唯讀ref引數 在c 中,唯讀引用 也可稱為 in引數 兩者提供了類似的限制。唯讀引用的基本思想是,如果用 re...

未來的C 之唯讀引用與結構體

c 中提供了const特性,使用該特性定義的引數,其所引用的引數或物件將不會被呼叫函式修改 當然const還提供了更多的特性,參見 const正確性 在新的建議中,c 也將提供類似的特性。唯讀ref引數 在c 中,唯讀引用 也可稱為 in引數 兩者提供了類似的限制。唯讀引用的基本思想是,如果用 re...

未來的C 之唯讀引用與結構體

c 中提供了const特性,使用該特性定義的引數,其所引用的引數或物件將不會被呼叫函式修改 當然const還提供了更多的特性,參見 const正確性 在新的建議中,c 也將提供類似的特性。唯讀ref引數 在c 中,唯讀引用 也可稱為 in引數 兩者提供了類似的限制。唯讀引用的基本思想是,如果用 re...