2012-06-12 24 views
15

當我在程序中使用const參數時,它有什麼不同?當我在過程的參數中使用「const」時,它會有什麼不同?

採取以下步驟,例如:

procedure DoSomething(Sender: TObject; const Text: String; var Reply: String); 
begin 
    //Text is read-only and Reply will be passed back wherever DoSomething() was called 
    Reply:= Text; 
end; 

參數Text: Stringconst使得前綴(據我所知),該值的拷貝進行和使用 - 和是隻讀的。我想知道的是,如果不在那裏放置const,它會如何影響應用程序?也許是一種表演技巧?

+1

在這裏回答? http://stackoverflow.com/a/1601124/496736 – 2012-06-12 17:25:23

+2

在大多數情況下,我認爲將所有僅用於輸入的參數標記爲「const」的主要好處是,程序員將獲得額外的幫助,避免愚蠢錯誤。 –

+1

@Andreas令人討厭的是'const'需要包含在接口和實現中。這是C++擊敗Delphi的一個領域。 –

回答

22

綜觀documentation狀態:

「使用常量允許編譯器優化爲結構化的代碼 - 和字符串型參數它還提供了對通過引用無意將參數傳遞給另一個例程的保障」

在字符串的情況下,例如優化意味着當傳遞爲const時沒有額外的計數。同樣以const傳遞而不是意味着它是一個副本。通常它會作爲參考內部傳遞,因爲編譯器確保無法對其進行寫入訪問。

一些非常有趣的文章,完全地瞭解發生了什麼引擎蓋下回事:

http://delphitools.info/2010/07/28/all-hail-the-const-parameters

http://vcldeveloper.com/articles/different-function-parameter-modifiers-in-delphi

編輯:

一個簡單的例子表明,常量可能導致路過內部參考:

program Project1; 

{$APPTYPE CONSOLE} 

type 
    PMyRecord = ^TMyRecord; 
    TMyRecord = record 
    Value1: Cardinal; 
    Value2: Cardinal; 
    end; 

procedure PassAsConst(const r: TMyRecord); 
begin 
    PMyRecord(@r).Value1 := 3333; 
    PMyRecord(@r).Value2 := 4444; 
end; 

procedure PassByVal(r: TMyRecord); 
begin 
    PMyRecord(@r).Value1 := 3333; 
    PMyRecord(@r).Value2 := 4444; 
end; 

var 
    r: TMyRecord; 
begin 
    r.Value1 := 1111; 
    r.Value2 := 2222; 
    PassByVal(r); 
    Writeln(r.Value1); 
    Writeln(r.Value2); 

    PassAsConst(r); 
    Writeln(r.Value1); 
    Writeln(r.Value2); 

    Readln; 
end. 
+3

FWIW:對於**如何通過**,參數是否爲常量無關緊要。如果它沒有明確聲明爲'var'或'out',那麼它將被**傳遞**,對於const或非const來說是相同的。通常,大於寄存器大小的項目(比如32位)將通過引用**傳遞**,無論它們是否爲常量。常量和非常量之間的唯一區別在於,對於非常量,隱藏代碼在將項目複製到本地存儲的開始時插入。對於const,只允許讀取引用,所以這個複製代碼丟失,直接使用傳遞的引用。 –

6

如果您沒有const前綴,編譯器必須假定您將更改該參數。這意味着要複製它並設置一個隱藏的try ...最後來處理本地的字符串變量,所以有時const會產生顯着的性能提升。它還使生成的代碼更小。

+0

我應該補充說,德爾福2007 - 這是我安裝的最新版本。我更高級的編譯器可能會檢測到一個參數實際上並沒有被用作一個變量,即使沒有const前綴也不會複製它,但這些優化類型歷來不是Delphi研發團隊的重點。 –

+0

在Delphi的所有版本中都知道const參數,即在D2007之前:無需複製結構,如果它們通過引用傳遞(這取決於它們的大小),本地存儲並且不需要做引用計數。 –

1

除了之前使用const的效率答案(即,編譯器不需要複製該變量),如果使用帶有Interface參數的const,它將阻止觸發ref計數。

+0

這是此行爲的原因:http://qc.embarcadero.com/wc/qcmain.aspx?d=75036 –

+3

缺少引用計數對於接口和字符串是相同的。你所說的關於接口的內容並不是「除了」關於字符串的東西。 *變量*一直被複制,但是複製這些變量很便宜,因爲它只是複製指針的值,有時不過是將值從一個寄存器複製到另一個寄存器。 –

相關問題