2014-10-09 50 views
5

假設我有一個unique_ptr成員對象,我想在類中初始化,請參閱下面的代碼。爲什麼我必須使用統一初始化(花括號)?第二個聲明吐出一個錯誤,像獨特的指針類初始化

so.cpp:10:31: error: expected parameter declarator 
std::unique_ptr<Foo> upf2(new Foo); 
         ^
so.cpp:10:31: error: expected ')' 
so.cpp:10:30: note: to match this '(' 
std::unique_ptr<Foo> upf2(new Foo);       ^
2 errors generated. 

而且我不認爲是一個最令人頭疼的解析問題,至少我不相信如此。

#include <memory> 

class Foo 
{ 

}; 

class Bar{ 
    std::unique_ptr<Foo> upf1{new Foo}; // works fine 
// std::unique_ptr<Foo> upf2(new Foo); // error here 
}; 

int main() 
{ 
    Bar bar; 
} 
+4

NSDMIs必須使用* brace-equal-initializer *。 – 2014-10-09 02:37:24

+0

@ T.C。謝謝,我不知道這是必須的。 – vsoftco 2014-10-09 02:40:16

回答

7

非靜態數據成員的初始值(NSDMI)必須使用支架 - 或等於初始值設定:當有直接和支架初始化之間的差異也可以是惱人的。不允許初始化的(expression-list)形式。

正如N2756所解釋的,爲了讓NSDMIs更像傳統的構造函數成員初始化列表,可以在整個類的範圍內查找初始化符內部的名稱。不幸的是,這意味着允許括號初始化,就不可能確定的東西是否是在當時的聲明被解析的初始化或函數聲明:

// not real code 
struct X { 
    int i(x); // initializer 
    static int x; 
}; 

struct Y { 
    int i(x); // function 
    typedef int x; 
}; 

本文討論了幾個可能的方式來解決這個短完全禁止它(「可以是聲明的所有內容都是聲明」或「除非你聲明這是一種類型,否則它不是一種類型」),但兩者都不具吸引力,並且認爲潛在的混淆可能超過允許此表單的好處的初始化。

+0

好點,我認爲這可能是某種最令人頭痛的解析問題,但無法自己拿出一個例子。謝謝! – vsoftco 2014-10-09 02:44:09

9

因爲這些是規則。課堂初始者必須使用「大括號」或「等於」;實際上,該句法元素被稱爲括號或等號初始化程序

int equals = 42;      // OK 
std::unique_ptr<Foo> braces{new Foo}; // Also OK 

我不知道爲什麼不允許使用括號;也許是爲了避免初始化看起來像函數聲明的可能性。

std::vector<int> bad(6);      // ERROR: parentheses not allowed 
std::vector<int> good{6};     // OK but not the same 
std::vector<int> ugly = std::vector<int>(6); // OK but ugly 
+0

謝謝,不知道規則。語法的確很煩人,特別是第二行'std :: vector good {6};',這不符合人們的想法。 – vsoftco 2014-10-09 02:42:43