在下一個程式中,B洗掉復制建構式的struct被拋出并被值捕獲:
struct B {
B() = default;
B(const B&) = delete;
};
int main() {
try {
throw B{};
}
catch( B ) {
}
}
Clang 拒絕了帶有預期錯誤的代碼:
error: call to deleted constructor of 'B'
catch( B ) {
然而GCC很好地接受了程式,演示:https : //gcc.godbolt.org/z/ed45YKKo5
哪個編譯器就在這里?
uj5u.com熱心網友回復:
叮當是對的。(感謝@NathanOliver 的評論。)
[except.throw]/3
拋出例外復制初始化([dcl.init],[class.copy.ctor])一個臨時物件,稱為例外物件。表示臨時值的左值用于初始化在匹配處理程式([except.handle])中宣告的變數。
[except.throw]/5
當拋出的物件是一個類物件時,為復制初始化選擇的建構式以及為將拋出的物件視為左值的復制初始化選擇的建構式應是不可洗掉和可訪問的,即使復制/移動操作被省略([class.copy.elision])。
例外物件被認為是一個左值,在catch子句引數的復制初始化中,選擇了復制建構式。作為優化,復制操作可能會被省略;但復制建構式仍然必須存在且可訪問。
我已將此報告為gcc bug 103048。
順便說一句,由于強制復制省略(C 17 起),由 引起的例外物件的復制初始化throw B{};很好。
在物件的初始化中,當初始化運算式是與變數型別相同型別別的純右值(忽略 cv 限定)時:
T x = T(T(f())); // only one call to default constructor of T, to initialize x
首先,如果 T 是一個型別別并且初始值設定項是一個純右值運算式,其 cv 非限定型別與 T 相同,則初始值設定項運算式本身,而不是從它具體化的臨時物件,用于初始化目標物件:參見副本省略(C 17 起)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/346609.html
