簡體   English   中英

函數參數或局部變量

[英]Function parameter or local variable

假設我有一個重復數百萬次的循環。 在這個循環里面我有一個函數調用。

在這個函數內部,我需要對一開始創建的一些臨時變量進行操作。 現在,哪一個更好:

a)在代碼的開頭創建臨時變量,在循環開始時初始化它,並將其作為函數參數傳遞

b)在被調用函數的開頭只創建本地臨時變量?

這是一個有問題的問題嗎? 我想知道哪一點被認為是更好的練習,哪一點更快。

讓我們為some_function()拋出一些可能的定義,這是你將從循環中調用的函數。

// Method 1
void some_function() {
    int temporary;

    // Use temporary
}

// Method 2
void some_function(int temporary) {
    // Use temporary
}

// Method 3
void some_function(int *temporary) {
    // Use *temporary
}

方法1可能是最可讀出的這些選項,因此它是一個我寧願除非你有一個很好的理由去做別的事情。 除非您的編譯器內聯函數調用, 否則它也可能比其他任何一個都快。 如果是,則所有三個都可能執行完全相同(如果編譯器無法優化指針解引用,方法3可能仍然會更慢)。

如果編譯器沒有內聯,那么方法2可能比方法1慢。這是因為,就堆棧分配的內存而言,它們是相同的 - 函數參數將以相同的方式存儲在堆棧中當地人是。 函數參數和此上下文中的局部唯一區別在於函數參數可以由調用者賦予值。 將值從調用者傳遞給函數的這一步驟(理論上)會減慢調用速度。

方法3幾乎肯定會變慢,因為對臨時存儲器的訪問將包括一個間接級別。 與訪問本地相比,取消引用指針並不是一種便宜的操作。

當然,如果性能絕對關鍵,那么您應該對這些方法進行基准測試。 我懷疑方法1會變得最快(或者至少不比其他方法慢),而且對我來說似乎更具可讀性。

如果在函數外部不需要變量,那么它應該在函數內部。 這允許編譯器最好地優化代碼,並使代碼最易讀和易於使用(這通常適用於“聲明具有最小可能范圍的變量”,盡管對於小函數,聲明少數每次函數頂部的變量是最佳選項)。

從性能角度來看,將變量傳遞給函數要么等效,要么比擁有局部變量更糟糕。 [當然,編譯器可能會內聯所有內容,但在這兩種情況下最終會得到完全相同的代碼,但這取決於編譯器和您擁有的代碼]。

正如其他人所提到的,將指針傳遞給局部變量將導致訪問指針以獲取值的“懲罰”。 它可能沒有太大的區別,但它幾乎肯定會產生一些不同。 這絕對是最后的選擇。 [注意,如果變量是LARGE,則將副本傳遞給函數的開銷可能仍然比指針的開銷更差。 但是如果我們假設它是一個簡單的類型,如intfloat ,那么指針有明顯的開銷]。

每當有關於性能的問題時,您肯定應該對您的代碼進行基准測試。 如果在排序算法或類似的算法之間做出選擇,那么在互聯網上詢問其他人可能是值得的,但如果在一些更微妙的差異中這是“更好地做這個或那個”的情況,那么差異往往是小而你的特定編譯器所做的將比“理論上更好”具有更大的影響力。

如果將變量作為指針而不是值傳遞, 這兩種方法之間存在細微差別。 指針將被推送到調用堆棧,並且必須被引用才能獲取/設置值。

相反,將其設置為本地值或按值傳遞將把值放在堆棧上。 在這種情況下,重要的不是它是局部值還是傳遞值...盡管有一個可能的警告,基於在傳遞值的情況下如何在函數之外處理變量...如果它存儲在一個變量(不傳遞文字值)然后它必須從內存中獲取並推送到堆棧上。 如果它是從函數內部的文字值設置的,那么它只是一個文字推入堆棧並保存了一個內存周期。

您省略的第三個選項是使用全局變量。

在值不變的情況下,值始終是,然后最佳答案使用#define並將其直接編譯為代碼作為文字。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM