2011-06-11 97 views
18

我正在讀FDIS(12.2p {4,5})的這兩段:當一個數組由子表達式創建時,其中的臨時對象會發生什麼?

有兩個上下文,其中的臨時被在不同的點比全表達的端部銷燬。第一個上下文是當調用默認構造函數來初始化數組的元素時。如果構造函數有一個或多個默認參數,則在構造下一個數組元素(如果有)之前,對在默認參數中創建的每個臨時對象的銷燬都進行排序。

的第二上下文是當引用綁定到一個暫時的。臨時到該參考結合或臨時即其上結合的參考持續基準的壽命除了一個子對象的完整的對象: [...]

  • 臨時結合到函數調用(5.2.2)中的引用參數將一直存在,直到完成包含調用的完整表達式。

這兩個2似乎與以下情況

struct A { 
    A() { std::cout << "C" << std::endl; } 
    ~A() { std::cout << "D" << std::endl; } 
}; 

struct B { 
    B(A const& a = A()) { } 
}; 

typedef B array[2]; 

int main() { 
    array{}; 
} 

將所要求的第一上下文此輸出CDCD,或將所要求的第二上下文此輸出CCDD? GCC似乎遵循第二個上下文描述並輸出CCDD。我忽略了一些重要的東西嗎?


編輯:我不認爲它需要C++ 0x。這new -expression是我的問題太受影響:

new array(); /* CDCD or CCDD ?? */ 

在這種情況下,雖然,GCC遵循第一上下文和輸出CDCD

+0

報道,希望它的一些GCC開發者評論:http://gcc.gnu.org/bugzilla/show_bug.cgi?id= 49372 – 2011-06-11 13:47:16

+0

奇怪:我的GCC 4.6沒有輸出。 - 啊,我看你有相同的看似錯誤的行爲:)對於它的價值:MSVS2010 SP1輸出CDCD ... – rubenvb 2011-06-11 13:49:06

+0

另外:8.5.4/4似乎暗示有*正常*沒有序列約束的論點一個電話。在這裏有關係,因爲GCC中的'new array()'情況打印了'CDCD'? – rubenvb 2011-06-11 14:12:27

回答

2

我不認爲有矛盾。

5.2.2清楚地說明函數調用是什麼。函數調用是一個後綴表達式,後跟括號 ,其中包含可能爲空的 逗號分隔的表達式列表 ,它們構成 函數的參數。

在程序中的任何地方似乎都沒有函數調用B::B(A const&),所以我沒有看到第二段文字是如何應用的。

EDIT上述可能不正確,因爲1.9p10等

+1

儘管我同意它有時會有點不清楚,但C++中的「函數調用」並不侷限於5.2.2所指定的語法。這只是一個函數的調用,它可能使用任何和所有語法,也可能是隱式的。請參閱1.9p15的註釋「儘管在翻譯單元中沒有出現相應的函數調用語法,但C++中的幾個上下文會導致函數調用的評估[例如:評估新表達式會調用一個或多個分配和構造函數;請參見5.3 .4 - ... - 結束示例]「。 – 2011-06-11 20:08:28

+0

5.2.2中的大部分通常適用於對函數的調用,而忽略了需要函數調用的上下文。我所引用的子彈可能只打算在明確使用函數調用語法時應用(我認爲在這裏有一些誤解的空間,這是不幸的,特別是因爲與5.2.2的交叉引用),但這似乎很奇怪,因爲這意味着許多表達式模板節點會導致未定義的行爲(因爲它們只保留對傳遞給它們的構造函數的參數的引用,並在它們的ctors運行很久之後引用它們)。 – 2011-06-11 20:12:42

+0

@johannes我會說這確實是一個不幸的措辭,因爲函數調用和運算符調用之間的確有很小的差別。但隱含的調用是不同的。隱式調用不是表達式,因此,不是任何完整表達式的一部分。有時候根本沒有任何驅逐與這種呼叫相關聯(例如在聲明中)。所以我仍然認爲第二個上下文不適用。 – 2011-06-12 00:38:38

相關問題