[英]Initializer in braces and parentheses - From Item 7 in Modern Effective C++
在《Effective Modern Cpp》一書的Chapter7,Item 7中,討論了創建對象時()和{}的區別。 然而,當我編譯並運行本章中列出的一些代碼時,我發現代碼的行為與注釋描述的不同。 我必須指出,我用於測試的代碼是我編寫的,因此與書中的原始代碼不完全相同,但它更簡單,足以涵蓋我的觀點。 而且我非常肯定,差異不會是我遇到的問題的原因。
PDF格式的書中感興趣的內容所在位置為第53頁第7項。
在本頁末尾,對代碼“Widget w6{w4};”的注釋說“使用大括號,調用 std::initializer_list ctor(w4 轉換為 float,float 轉換為 long double)”。 然后,我在下面寫了我的代碼只是為了定期驗證,直到我看到代碼的 output 之前,我並沒有期待任何異常。
#include <iostream>
using namespace std;
class Widget {
public:
Widget(int i) : _i(i){
cout << "call to Widget(int i)" << endl;
}
Widget(Widget& w) {
_i = w._i;
cout << "call to Widget(Widget& w)" << endl;
}
Widget(initializer_list<int> il) {
if (il.size() > 0) {
_i = *(il.begin());
}
cout << "call to Widget(initializer_list<int> il)" << endl;
}
void print_info() {
cout << "_i: " << _i << endl;
}
operator int() const {
// return a fixed value just for testing
return 100;
}
private:
int _i;
};
// this is the testbed
int main() {
Widget w1{10, 5};
w1.print_info();
cout << "----------------------------------------" << endl;
Widget w2{{w1}};
w2.print_info();
cout << "----------------------------------------" << endl;
Widget w3{w1};
w3.print_info();
return 0;
}
代碼的 output 就像
~/CppTest/move_construct g++ -std=c++17 -o run test.cpp ✔ 11:49:11
~/CppTest/move_construct ./run ✔ 11:49:26
call to Widget(initializer_list<int> il)
_i: 10
----------------------------------------
call to Widget(initializer_list<int> il)
_i: 100
----------------------------------------
call to Widget(Widget& w)
_i: 10
如您所見,使用大括號初始化 w2 的初始化 w1 被包裹在另一層大括號中,其行為與書中的注釋完全相同。 但是使用單層大括號初始化的 w3 只是復制構造的。
我不知道這是編譯器的進化、cpp 標准還是我忽略的某種編譯器配置造成的。 我正在使用的編譯器的信息是:
Apple clang version 12.0.5 (clang-1205.0.22.11)
Target: x86_64-apple-darwin21.3.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
謝謝並期待您的答復。
當這本書可能寫成時,它是正確的,因為std::initializer_list
構造函數應該優先於復制構造函數。
然而,隨后CWG 1467更改了規則,結果是復制構造函數將成為首選。
然而,這可能只是一個意外的副作用,因為這些規則只是為了修復聚合類的行為,所以CWG 2137再次修改了規則,使std::initializer_list
構造函數與原始行為一樣成為首選。
您似乎正在使用 Clang,它恰好還沒有實現后一個缺陷報告,請參閱此打開的錯誤報告。
所以最終書還是對的,只是編譯器沒有跟上規則的變化。
GCC 產生預期的 output。有趣的是,MSVC 在嘗試編譯您的代碼時有一個內部編譯器錯誤(所以也是一個錯誤): https://godbolt.org/z/TKcEzn1be
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.