2014-10-09 11 views
5

Supponiamo di avere un oggetto membro unique_ptr che desidero inizializzare in classe, vedere il codice seguente. Perché devo utilizzare l'inizializzazione uniforme (parentesi graffe)? La seconda dichiarazione sputa un errore, qualcosa comeInizializzazione univoco del puntatore nella classe

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. 

E non credo sia un problema di parse più fastidioso, almeno io non lo credo.

#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

Gli NSDMI devono utilizzare un inizializzatore * controvento o uguale *. –

+0

@ T.C. grazie, non sapevo che fosse obbligatorio. – vsoftco

risposta

7

un membro di dati di inizializzazione non statico (NSDMI) devono utilizzare un brace-o-uguale-inizializzatore. La forma di inizializzazione (expression-list) non è consentita.

Come spiega N2756, per consentire agli NSDMI di comportarsi più come gli elenchi di inizializzatori dei membri del costruttore tradizionale, i nomi all'interno degli inizializzatori vengono esaminati nell'ambito di tutta la classe. Sfortunatamente, questo significa che permettere parentesi initializers renderebbe impossibile determinare se qualcosa è un inizializzatore o di una dichiarazione di funzione, al momento della dichiarazione viene analizzato:

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

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

Il documento ha discusso un paio di possibili modi per risolvere questo corto di vietandogli del tutto ("tutto ciò che può essere una dichiarazione è una dichiarazione" o "non è un tipo a meno che tu non dica che è un tipo"), ma nessuno dei due è molto allettante, e la potenziale confusione era considerata superiore al beneficio di permettere questo modulo di inizializzazione.

+0

Un buon punto, ho pensato che potesse essere una sorta di problema di parse molto irritante, ma non sono riuscito a trovare un esempio da solo. Grazie! – vsoftco

9

Perché quelle sono le regole. Gli inizializzatori di classe devono utilizzare "bretelle" o "uguali"; infatti, l'elemento sintattico è chiamato inizializzatore di coppia o uguale.

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

Non so perché le parentesi non siano consentite; forse per evitare la possibilità che l'inizializzazione assomigli a una dichiarazione di funzione. Può essere fastidioso quando c'è una differenza tra inizializzazione diretta con bretelle:

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

Grazie, non conoscevo la regola. La sintassi è davvero piuttosto fastidiosa, specialmente la seconda riga 'std :: vector good {6};', che non fa ciò che si può pensare. – vsoftco