2011-12-15 66 views
16

我試圖瞭解const refin之間的區別,特別是當涉及到性能時。'const ref'和'in'之間的區別?

  1. 我知道in相當於const scope,但到底是什麼the scope stor­age class means that ref­er­ences in the pa­ra­me­ter can­not be es­caped (e.g. as­signed to a global vari­able).是什麼意思?示例代碼是受歡迎的。

  2. 實現函數時,我如何決定在const refin之間?我知道與ref該對象不會被複制,因爲它是一個參考,但與in是一樣的真實?

回答

10

1)scope參數存儲類意味着您不允許轉義對參數的引用。例如:

Object glob; 

struct S 
{ 
    Object o; 
    void foo(scope Object o) 
    { 
     this.o = o; // Not allowed! 'o' must not be escaped 
     glob = o; // ditto 
    } 
} 

請注意,DMD並不是很擅長檢測此問題。上面的例子目前正在編譯,但不被允許。

scope是最有用的委託參數:

void foo(scope void delegate() dg) 
{ 
    /* use dg */ 
} 

void main() 
{ 
    int i; 
    foo({ ++i; }); 
} 

在上面的例子中,沒有閉合需要分配的,即使它有一個的upvalue匿名函數,因爲foo「保證」(它是編譯器的工作......)委託沒有被轉義。 DMD目前確實實施了這種優化。

2)我認爲這個想法是,當constscope被使用時,編譯器理論上可以通過引用或值隨意傳遞,這就是爲什麼in快捷方式是有用的。 DMD現在沒有利用這個優勢,但它仍然是一個方便的捷徑,它具有一些文檔價值。

簡而言之,in目前不會爲您帶來任何效果,除非它在委託上使用。 ref可以通過大型結構或靜態數組獲得一些性能。當出於性能原因使用ref時,const經常用於記錄(並強制執行)ref而不是用於更新原始值。

+0

1.好,這就解釋了爲什麼我無法重現這種效果。 2.所以,你是說如果一個函數的參數有'in'存儲類,它會被複制?我應該使用'const ref'嗎? – Arlen

+0

使用當前的編譯器選擇,全部基於DMD,它會被複制。但關於它的巧妙之處在於它仍然在技術上實現定義,因爲用戶無法區分差異。爲了DMD利用這個優化,它需要首先完全實現'範圍'。如果您已將複製標識爲瓶頸並且想要優化,那麼使用'const ref'是個好主意。 –

+0

你怎麼知道DMD這麼多?你是核心開發人員之一嗎? – Arlen

10
  1. 這對於scope參數來說是不合法的。編譯器應該保證沒有對該數據的引用轉義該函數。它主要用於委託,因爲它允許編譯器避免分配閉包,因爲它知道委託不會轉義。

  2. const refconst - 就像in會 - 但變量通過引用傳遞而不是被複制,所以你避免了副本。但是,不像C++const ref確實不是工作與rvalues。它必須被賦予一個左值。所以,如果你聲明一個參數爲const ref,它會限制你可以傳遞給它的東西。您通常必須聲明一個變量才能傳遞給它,而in將接受臨時變量。

    void func(const ref int var) {} 
    int a; 
    func(a); //legal 
    func(7); //illegal 
    

無論這些電話的是法律,如果funcconstin。所以,一般來說,問題不是你應該使用const ref還是in。問題是你是否應該使用constin。在這種情況下,問題是您是否要使用scope,因爲它們都是const。如果你想確保你傳入的變量沒有引用將會轉義該函數,那麼你使用scope,所以它通常只用於委託,但可以用於類或數組。

然而,pure上的功能保證任何它的參數沒有引用可以除了通過返回值(因爲如果他們是不可變的或都是值類型,並常量pure功能只能使用全局變量)逸出,使pure通常爲您提供所需的所有類和數組參數。另外,如果返回類型是一個類或數組,那麼您一般不希望這樣做,以至於參數無法轉義,因爲那麼不能從返回值中的這些參數中重用任何東西,函數被迫做一個副本,這通常效率較低。

因此,scope通常只用於委託,但有時對類或數組很有用。無論如何,函數通常最好是pure,這樣可以解決大部分問題。因此,儘管使用in並沒有什麼壞處,但使用in而不是const通常沒有什麼意義。如果你真的想要避免複製被傳入的變量,你通常只使用const ref,否則你只能通過左值到那個函數。你可以超載一個功能,它的版本需要const和一個需要const ref,但很明顯會導致代碼重複,所以除非你真的想要const ref,否則它可能只是最好使用const

編輯:

scope尚未超過委託任何其他(截至2013年6月18日)來實現,因此,使用或者scopein比代表以外的其他項不明智的。目前,它們是誤導性的,並且如果/一旦scope針對代理以外的任何其他實現,則由於引用標記爲scopein的變量而導致代碼中斷的風險很高。

+0

這是不是真的,因爲'範圍'沒有在DMD中完全實現,'in'不是應該這樣應付它的方式嗎?一旦'範圍'完全適用於那些不正確使用'in'的人,它不會是一個突破性的改變嗎? – Arlen

+0

假設'範圍'是錯誤的(它可能是非常好的;我沒有用太多,所以我不完全確定它的當前狀態),那麼是的,這將是任何代碼的突破性改變錯誤地使用了'scope'或'in',但這與幾乎任何編譯器錯誤都是一樣的。幸運的是,由於轉向github以來發展速度很快,dmd中這類問題的數量一直在大幅下降,但當然還有可能遇到功能未正確實施的問題。 –

+0

'scope'並不是真的有問題,除非進行優化,否則根本沒有實現。 'pure'幾乎不是'scope'的好選擇,因爲使用'pure'成員函數,您仍然可以通過將參數賦給成員字段來將參數轉義,而'pure'具有其他不相關的限制。如果'scope'完全實現了,那麼對於很多情況是很有用的,比如能夠安全地傳遞slice來將內存堆棧到一個用'scope'接收它的函數。 –

相關問題