[英]What is the order of destruction of function arguments?
如果分別使用參數a_1
,..., a_n
調用類型分別為T_1
,..., T_n
參數p_1
,..., p_n
的某些函數f
,並且其主體將引發異常,結束或返回,則函數f
順序為論據遭到破壞,為什么? 如果可能,請提供該標准的參考。
編輯:我實際上想詢問函數“參數”,但是由於TC和Columbo設法清除了我的困惑,我將這個問題留給參數,並詢問有關參數的新的單獨問題 。 有關區別,請參閱有關此問題的評論。
我沒有在標准中找到答案,但是我能夠在3種最流行的C ++兼容編譯器上進行測試。 R Sahu的答案在很大程度上解釋了它是實現定義的。
§5.2.2/ 8 :后綴表達式和參數的求值相對於彼此都是無序的。 在輸入函數之前,對參數評估的所有副作用進行了排序。
Visual Studio C ++編譯器(Windows)和gcc(Debian)
按照與聲明相反的順序構造參數,並按照相反的順序銷毀它們(因此按委托順序銷毀):
2
1個
-1
-2
lang(FreeBSD)
按照聲明的順序構造參數,並以相反的順序銷毀它們:
1個
2
-2
-1
指示所有編譯器將源代碼視為C ++ 11,我使用以下代碼片段演示了這種情況:
struct A
{
A(int) { std::cout << "1" << std::endl; }
~A() { std::cout << "-1" << std::endl; }
};
struct B
{
B(double) { std::cout << "2" << std::endl; }
~B() { std::cout << "-2" << std::endl; }
};
void f(A, B) { }
int main()
{
f(4, 5.);
}
在§5.2.2[4]中, N3337非常清楚地說明了發生的情況( 在線草案 ):
在參數初始化期間,實現可以通過將對關聯自變量的轉換和/或臨時變量的構造與參數的初始化相結合來避免額外的臨時變量的構造(請參見12.2)。 參數的生存期在定義它的函數返回時結束。
因此,例如
f(g(h()));
調用h()
的返回值是一個臨時值,將在完整表達式的末尾銷毀。 但是,允許編譯器避免此暫時情況,並直接使用其值初始化g()
參數。 在這種情況下,一旦g()
返回(即在調用f()
之前g()
,返回值將被銷毀。
如果我正確理解了標准中的規定,則不允許從h()
返回的值保留到完整表達式的末尾,除非進行了復制(參數)並且一旦g()
銷毀了該副本返回。
這兩種情況是:
h
返回值用於直接初始化g
參數。 當g
返回並且調用f
之前,此對象被銷毀。 h
返回值是臨時的。 復制副本以初始化g
參數,並在g
返回時銷毀它。 原始臨時臨時文件會在完整表達式的末尾銷毀。 我不知道實現是否遵循此規則。
標准未指定評估函數參數的順序。 根據C ++ 11標准( 在線草案 ):
5.2.2函數調用
8 [ 注意:后綴表達式和自變量表達式的求值相對於彼此都是未排序的。 在輸入函數之前,對參數表達式求值的所有副作用進行了排序(請參見1.9)。 —尾注 ]
因此,完全取決於實現來決定以什么順序評估函數的參數。 反過來,這意味着參數的構造順序也取決於實現。
明智的實現將以與對象相反的順序破壞對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.