簡體   English   中英

C ++-const參數和類變量是否被簡化?

[英]C++ - Are const parameters and class variables pessimization?

我試圖弄清楚編寫C ++代碼時應何時使用const。 這些都是悲觀的例子嗎?還是這樣寫代碼有益?

范例1:

int findVal(const int OTHER_VAL) const
{
    switch(OTHER_VAL)
    {
    case 1:
        return 2;
    default:
        return 3;
    }
}

范例2:

enum class MobType
{
    COW, CHICKEN, DOG, PIG
};

class BaseMob
{
protected:
    BaseMob(const MobType TYPE) : TYPE(TYPE) { }

    const MobType TYPE;
};

范例3:

void showWorld(const World &world)
{
    auto data = world.getData();
    for (auto &i:data)
        i.print();
}

不,不是。

具有自動存儲功能的局部變量(包括函數args)上的const純粹是語法糖,可幫助人類程序員為其代碼設置規則。 它根本沒有幫助優化器。 優化的編譯器從C源代碼中提取必要的數據移動,然后對其進行優化。 他們通常不在乎您是否將同一個tmp變量用於許多不同的事情,或者有10個不同的const tmp1 = a+10; 在相同的功能。

是的,這適用於按值傳遞的函數args。 它們是具有自動存儲的局部變量,可以傳入寄存器或在堆棧中傳遞。 不,這並不意味着調用者可以認為函數沒有修改用於arg傳遞的堆棧內存,因此也對優化器沒有太大幫助 (使用相同參數進行第二次函數調用仍需要將args重新寫入堆棧(如果並非所有args都適合寄存器),因為arg上的const不會改變被調用函數“擁有”以下事實的事實:堆棧空間,並可以根據需要將其用作臨時空間。)


const靜態/全局/引用變量確實有幫助。 static const int foo = 10; 可以作為立即常量內聯而不是從內存中加載。 (例如, add eax, 10而不是add eax, 10而不add eax, [foo] )。


使用const將類方法標記為不更改任何類成員也可以幫助編譯器避免在函數調用后重新加載類成員。 (即將它們保留在寄存器中)。 這僅在編譯器看不到函數定義的情況下才適用,否則,一個好的優化編譯器可以僅查看被調用函數的功能並相應地進行優化。 (只要它不在Unix庫中,其中的符號插入意味着它不能假定它在編譯時看到的被調用函數將是動態鏈接之后被調用的函數。)

只要邏輯上不更改值或對象,就應將其設置為const 從邏輯上講,我並不是指每次在技術上都允許您這樣做,而是每次在您的函數,類和代碼的上下文中都是合乎邏輯的。

一個簡單的示例可以是示例1中所示的簡單“ get”函數,這些函數不應修改類的狀態,因此應將其標記為常量,因為這將有助於向用戶說明您的意圖,同時還可以幫助您確保類的不變性。

如例2所示,在某些情況下,使不可變的對象有意義。在C ++中我們並不經常看到它們,但是許多其他語言經常使用它們。 如果它沒有添加任何值以能夠在對象生存期內更改某個成員,則最好將其設置為const。

傳遞const引用參數可為您提供引用的性能優勢,但同時可確保源對象保持不變,這對用戶而言既是不錯的文檔,又可進行som優化。

提到了所有這些原因之后,還有其他原因使用const如上一段優化中所述。 當編譯器知道某些內容是恆定的並且沒有被更改時,它可以啟用一些非常聰明的優化,但是出於性能原因,請不要使用const

這也是為什么通過(例如) const_cast (可以丟棄const會導致某些不良行為的原因。 作為示例,請檢查以下內容:

#include <stdio.h>

static const int foo = 10;

int constsum(void) {
  return foo + 5;
}

int main(int argc, char* argv[]) {
  int a = constsum();
  int* newFoo = const_cast<int*>(&foo);
  *newFoo = 20;
  int b = constsum();
  printf("%d\n", a + b);
  return 0;
}

從該示例可以看出( 請參閱此處運行的代碼 ),這可能不會產生期望的結果,因為該代碼導致打印30 ,而不是預期的40。

在檢查生成的程序集時,我們可以看到原因( 編譯為程序集 ):

constsum():
        mov     eax, 15
        ret
main:
        mov     eax, 30
        ret

編譯器只是內聯這些值,因為它們可以看到它們是常量,因此不必特別注意正在使用const_cast

因此const的正確性和const使用是一個有價值的工具,它可以提高代碼的性能和穩定性,但同時(不要忘記)它有助於記錄代碼。

暫無
暫無

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

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