標籤:

C++11中用{}初始化,有等於號和沒等於號的區別是什麼?

之前一直以為兩者是等價的,但今天用tuple的時候發現,在G++5.1.0下

tuple& s = {1, "1234"};
tuple& s{1, "1234"};

前者編譯報錯,報錯信息是

error: converting to "std::tuple&, std::allocator& &> &>" from initializer list would use explicit constructor "constexpr std::tuple&<_T1, _T2&>::tuple(_U1, _U2) [with _U1 = int; _U2 = const char ()[5]; & = void; _T1 = int; _T2 = std::__cxx11::basic_string&]"

後者可以順利編譯

根據報錯信息,編譯器好像是想把initializer list轉換成tuple,但由於tuple的構造函數是explicit的,所以編譯失敗

為什麼它會把{}看作initializer list呢?initializer list不應該是相同類型的嗎?{1, "1234"}顯然是不同類型的呀?而且我去查了下tuple頭文件,裡面並沒有以initializer list為參數的構造函數呀?

如果把有等於號的看作隱式轉換的話,那當{}為構造函數的時候又該怎麼理解呢?比如

using namespace std;
struct node {
int a, b;
node(int a, int b) : a(a), b(b) {}
};
int main() {
node s = {1, 2};
}

這兩種寫法到底有什麼區別呢?


第一種叫copy-initialization, 第二種叫braced-initialization,若你要完整的知道失敗的原因,你需要知道標準對這兩者的差別:Effective Modern C++ Note 01,可以參考我這個文章裡面提到當構造函數是explicit的時候,copy-initialization失敗的原因。


前者是構造struct的語法糖,後者才是「通用初始化」,可以適用各種場合。


那就用

auto s = make_tuple(1, string("1234"));


有等於號的叫做隱式轉換構造,而tuple(C++14還是17之前)是不允許隱式轉換構造的

至於你說的initializer list,不要和std::initializer_list&混淆,前者是從C時代就有的概念,就是指那個花括弧和裡面包的東西


在我看來,題主的例子正是這兩者唯一的區別,即帶等號的copy-list-initialization不允許調用explicit構造函數。此規定見 [over.match.list] :

In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.

由此延伸出的引用的列表初始化也是一樣:

struct A {
explicit A(int);
};
const A a1 = {0}; // error
const A a2{0}; // ok

歡迎指出其他具體的不同之處。

順便,C++17後std::tuple的構造函數不再總是explicit,用copy-list-initialization也可以了。


C++17已經fix了吧,不會默認把這個當做 initializer_list


std::tuple::tuple - cppreference.com

Conditionally-explicit constructors in C++17 make it possible to construct a tuple in copy-initialization context using list-initialization syntax

g++ Chapter 1. Status:

Improving pair and tuple N4387 6.1

N4387: Improving Pair and Tuple (Revision 3)

https://godbolt.org/g/LKcuui


推薦閱讀:

聲明多個指針時,為什麼實際只有第一個是指針?
cpp 如何 debug memory leak?
C++中類的構造函數,成員變數是在初始化列表初始化還是在函數體中進行賦值?
cout << sizeof(vector<int>);輸出是32,為什麼?
如何用 VS 2013 打包 VC++ 程序?

TAG:C |