以下是否應在 c 11 規則下編譯?為什么應該或為什么不呢?有UB嗎?似乎 gcc 之前禁止它,但在版本 11 中改變了主意。微軟接受它,而 clang 始終不接受。
我的表達方式是,IntWrapper myInt = 42;
在這種情況下只是語法糖,并且IntWrapper myInt(42);
與賦值運算子的多載對初始化沒有影響。在我看來,舊版本 gcc 和所有版本的 clang 都想做ctor(int)
,然后是move
. 雖然 msvc 和新版本的 gcc 只是呼叫ctor(int)
我認為是正確的。為什么在不需要的時候采取行動。
如果某些 c 語言律師可以將其翻譯成英文,請參見此處的 11.10.1 顯式初始化頁面 294-295 https://isocpp.org/files/papers/N4860.pdf
或者,可以使用 = 初始化形式將單個賦值運算式指定為初始化程式。直接初始化語意或復制初始化語意都適用;
注意:賦值運算子 (12.6.2.1) 的多載對初始化沒有影響。—
我對標準的理解是,編譯器可以選擇先復制然后再移動,或者使用帶有一個引數的 ctor 直接初始化。這會很奇怪,因為你怎么知道它是否編譯。
#include <iostream>
struct IntWrapper
{
IntWrapper(int value) : m_value(value)
{
std::cout << "ctor(int)\n";
}
IntWrapper(IntWrapper&& that) = delete;
int m_value;
};
int main()
{
IntWrapper myInt = 42;
return 0;
}
編譯器 | 結果 |
---|---|
msvc v.19.x | 編譯 |
gcc 11.x | 編譯 |
gcc 10.x | 錯誤:使用已洗掉的函式 'IntWrapper::IntWrapper(IntWrapper&&) |
鏗鏘聲14.0.0 | 錯誤:復制“IntWrapper”型別的變數呼叫已洗掉的建構式 |
鏗鏘聲13.0.0 | 錯誤:復制“IntWrapper”型別的變數呼叫已洗掉的建構式 |
鏗鏘聲12.0.0 | 錯誤:復制“IntWrapper”型別的變數呼叫已洗掉的建構式 |
uj5u.com熱心網友回復:
msvc v.19.x 和 gcc 11.x 都默認使用 C 17 作為編譯的語言標準,而您使用的所有其他編譯器默認使用 C 14。這就是為什么你看到了不同。
在 C 17IntWrapper myInt = 42;
被語意處理之前,IntWrapper myInt = IntWrapper(42);
您需要一個未洗掉的副本或移動建構式來編譯它,即使通過編譯器優化洗掉了臨時物件。
由于現在將 C 17IntWrapper myInt = 42;
視為已完成IntWrapper myInt{42};
,現在我們正在直接構造,因此不會創建臨時物件。此功能稱為保證復制省略
當標準說
直接初始化語意或復制初始化語意都適用;
他們的意思是IntWrapper myInt = 42;
可以被視為IntWrapper myInt = IntWrapper(42);
or IntWrapper myInt{42};
。這取決于您是否打開了優化,您獲得了哪種形式。可以在[class.temporary]/1中找到在 C 17 之前導致此失敗的標準的附加部分
即使臨時物件的創建未被評估(子句 [expr])或以其他方式避免([class.copy]),所有語意限制都應得到尊重,就好像臨時物件已被創建并隨后被銷毀一樣。[注意:這包括可訪問性([class.access])以及是否洗掉,對于選擇的建構式和解構式。但是,在用作 decltype-specifier ([expr.call]) 運算元的函式呼叫的特殊情況下,不會引入臨時值,因此上述內容不適用于任何此類函式呼叫的純右值。——尾注]
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/469963.html
上一篇:宣告一個constexpr靜態成員,它是模板引數中可能不存在的成員的函式?
下一篇:我們可以取xvalue的地址嗎