[英]Order of Evaluation for passing function arguments - Order of operations for F1( int F2( int& x ), int x )
好吧,所以我早些時候寫了一些代碼。 具體來說是這樣的:
EnterNode( FindNode( terrain_X, terrain_Y, travel_dir ), travel_dir );
在測試程序后,我注意到發生了一些奇怪的事情。 外部函數接收的值不是檢查堆棧時讀取的值。
我編寫了一個示例程序: https : //ideone.com/wNjJrE
#include <iostream>
int modifyRef(int& A)
{
A = 0;
std::cout << "\nint& A = 0";
return A;
}
void TakeValues(int X, int Y)
{
std::cout << "\nX = " << X;
std::cout << "\nY = " << Y;
}
int main()
{
int Q = 9;
TakeValues(modifyRef(Q), Q);
std::cout << std::endl;
system("pause");
return 0;
}
這是我收到的輸出:
int& A = 0
X = 0
Y = 9
我希望Y也為0。如何將參數綁定到函數調用的操作順序定義為?
(如果我使用的術語不正確,我深表歉意。)
未指定函數參數的評估順序。 當你寫:
TakeValues(modifyRef(Q), Q);
您依賴的事實是, modifyRef(Q)
在Q
之前要求Q
。 但是函數參數的求值順序未指定-不一定要在Q
之前對modifyRef(Q)
進行排序,反之亦然。
在這種情況下, Q
(第二個參數)首先被求值。 因此,我們讀取9
,並使用它初始化參數Y
然后 ,我們評估modifyRef(Q)
其中零出Q
並將其返回,導致初始化X
與0
。
嘗試更改功能的簽名:
int ModifyRef( int& A );
void TakeValues( int X, int Y );
到以下...
int& ModifyRef( int& A );
void TakeValues( int& X, int& Y );
並在調用以下代碼行時查看輸出將在main中顯示:
int q = 9;
TakeValues( ModifyRef(q), q );
然后像這樣顛倒參數的順序
TakeValues( q, ModifyRef(q) );
並比較結果。
當我在使用Intel Core2 Quad Extreme的VS2015社區的Win 7 64位計算機上執行此操作時,在使用引用的兩種情況下給出的結果都是相同的,並且得到的輸出是:
為了測試目的,我將ModifyRef()
的A
值從0更改為7。
int& A = 7
X = 7
Y = 7
對於兩種情況,其中內部函數是第一個參數,獨立變量是第二個參數,或者內部函數是第二個參數,獨立變量為第一個參數。
由於我收到了相同的結果,對我來說似乎對編譯器創建和處理堆棧指針的方式ModifyRef()
似乎首先對ModifyRef()
進行了評估,並且一旦該函數完成,因為現在引用了q
而不是將其作為堆棧副本,它會被ModifyRef函數中設置的任何值覆蓋。
我還稍微修改了ModifyRef()
函數,以便可以看到其傳入的參數是什么,而不是將數字硬編碼到其輸出語句中。
int& ModifyRef( int& A ) {
A = 7; // Changed Value From 0 To 7 For Testing Purposes
std::cout << "n\int& A = " << A;
return A;
}
但是,僅當僅使用引用時,此效果可能才適用。
當我恢復為原始函數簽名並按以下順序調用它時:
q = 9;
TakeValues( ModifyRef( q ), q );
由於您的原始代碼已顯示,因此我得到的輸出是:
int& A = 7
X = 7
Y = 9
但是,當我將參數反轉為:
q = 9;
TakeValues( q, ModifyRef( q ) );
我的輸出是:
int& A = 7
X = 7
Y = 7
因此,我在這兩種情況下看到的內容略有不同。
在參數的第一順序中,當q
初始化為9時,將Y
或第二個參數設置為9,並且TakeValues()
Y
打印出值為9的堆棧副本。然后X
由ModifyRef()
其中q
的值為9,但是由於它是一個引用而被修改,因此當TakeValues()
從q
設置X
時, q
已經從9更改為7,因此現在將X
設置為7。
在第二個參數順序中,似乎首先調用ModifyRef()
並將q
從9更改為7,因此TakeValues()
將Y
設置為7,並且由於此函數使用引用,所以q
也從9更改為7。當第一個參數使用q
設置X
q
已從9更改為7。
我不知道這是否與編譯器有關,但是至少在我的機器上,似乎參數的調用堆棧是從最右邊到最左邊發生的。 考慮到這是有意義的,因為函數具有默認值。
例:
class foo {
void bar( int a, int b, int c = 3 ) {
std::cout << a << ", " << b << ", " << c << std::endl;
}
};
函數聲明中的所有默認值都必須在最右邊,因為您不能擁有:
class foo {
void bar( int a = 1, int b, int c ) { ... } // Compile Error
};
我希望這有助於闡明當您開始使用按值(堆棧復制)或按引用傳遞時,開始在函數中調用函數作為參數時代碼中的情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.