簡體   English   中英

如何確定C ++函數的調用順序?

[英]How to determine C++ function call order?

我將跳過標題

class X {
    int i;
    static int j;

public:
    X(int ii = 1) : i(ii) {
        j = i;
    }
    static int incr() {
        return ++j;
    }
    static int f() {
        return incr();
    }
};

int _tmain(int argc, _TCHAR* argv[]) {
    X x;
    X* xp = &x;
    cout << x.f() << xp->f() << X::f();

    return 1;
}

該序列打印了432,但乍看之下可能會認為它將打印234。

如何確定函數調用的確切順序? 我想念什么?

流運算符只是一個運算符。 C ++允許使用多種方式定義運算符。 您所看到的是字符串的<<操作符。 您正在執行的操作與以下操作相同:

cout << "word1" << "word2" << "word3";

預期的輸出是:

"word1word2word3"

但是,評估順序由<<操作符的實現確定。 通常以上內容等同於:

   (((cout << "word1") << "word2") << "word3");

用函數代替字符串,您會看到第一個被評估的實際上是“ word3”。 嚴格來說,情況並非如此,只是您通常會看到的。

   (((cout << func1()) << func2()) << func3());

評估順序為func3,func2,func1,打印順序為返回func1,func2,func3。

1.9.13節

之前排序的是由單個線程(1.10)執行的評估之間的非對稱,可傳遞,成對關系,這會導致這些評估中的部分順序。 給定A和B的任何兩個值,如果A在B之前排序,則A的執行應在B的執行之前。如果A在B之前未排序,並且B在A之前未排序,則A和B不排序。 [注意:無序列評估的執行可能會重疊。 [尾注]當在B之前先對A進行排序,或者B在A之前對B進行排序時,可以不確定地對評估A和B進行排序,但不確定。 [注意:不確定順序的求值不能重疊,但是可以先執行。 —尾注]

換句話說,調用函數的順序是未定義的。 這並不意味着“我們不知道”,也不意味着“您無法解決” –這意味着它被定義為沒有定義; 編譯器和cpu可以按任何順序自由完成它們。

考慮以下:

int a[3];

void f1() { a[0] = 1; }
void f2() { a[1] = 2; }
void f3() { a[2] = 3; }

int main() {
    f1(), f2(), f3();
}

基本上,該語言不要求對類似這樣的語句進行排序

std::cout << f1() << f2() << f3();

您的代碼在函數調用之間沒有序列點( http://en.wikipedia.org/wiki/Sequence_point ); 您可以弄清楚編譯器生成的順序,但是在不同的CPU或不同的優化級別上,其行為可能有所不同。

如果您有這樣的可變函數調用,則需要手動提升或添加中斷:

std::cout << f1();
std::cout << f2();
std::cout << f3();

要么

auto a1 = f1();
auto a2 = f2();
auto a3 = f3();
std::cout << a1 << a2 << a3;

這個說法

cout << x.f() << xp->f() << X::f();

可以像這樣重寫

cout.operator <<( x.f() ).operator <<( xp->f() ).operator <<( X::f() );

未指定在此語句中用作參數的表達式的求值順序。 因此,編譯器可以從左到右或從右到左評估它們。 因此,使用不同的編譯器,您可以獲得不同的結果。

為了獲得確定的結果,您應該重寫語句

cout << x.f() << xp->f() << X::f();

例如像

cout << x.f();
cout << xp->f();
coit << X::f();

暫無
暫無

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

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