Non capisco perché questo compili


80

Mi manca sicuramente qualcosa, ma non capisco perché questo compili (sia con g ++ che con clang ++):

struct A
{
};
struct B
{
};

int main()
{
  A a(B);
}

Prima di tutto, Bè un tipo ... non un valore. Come devo interpretare questo codice?


37
Questo è noto come il più
fastidioso analisi

8
@alterigel È davvero? In questo caso non c'è ambiguità. Può essere solo una dichiarazione di funzione. Non è A a(B());quale potrebbe essere una definizione variabile o una dichiarazione di funzione.
noce,

8
Saresti sorpreso di sapere che si struct A{}; int main() { A(foo); } compila così com'è , anche se foonon nomina nulla.
Ayxan,

20
@alterigel - questa non è l'analisi più irritante. Guarda gli esempi nella pagina a cui ti sei collegato. Questa è semplicemente una dichiarazione di funzione.
Pete Becker,

3
@PeteBecker, potrebbe essere meglio spiegare perché questo non è MVP invece di affermare semplicemente che non lo è, cosa che credo non abbia già fatto in precedenza.
JPhi1618,

Risposte:


84

Viene interpretato come la dichiarazione di una funzione denominata a, che accetta un argomento di tipo Be restituisce A.


5
Ed è per questo che è Most e Vexing. Una soluzione: (non che risolva effettivamente nulla poiché espone la cattiva costruzione)A a{B};
user4581301

23
@ user4581301 - non è l'analisi più fastidiosa. È semplicemente una dichiarazione di funzione.
Pete Becker,

23
Quindi si scopre che è solo un'analisi in gran parte
irritante

11
La parte più strana proposito è che C ++ non consente funzioni nidificate, ma non consente dichiarazioni all'interno di una funzione.
The_Sympathizer il

6
Sembra una buona motivazione per aggiungere il supporto per le funzioni nidificate in C ++; non solo sarebbero utili, trasformerebbero questa strana verruca in un design ragionevole :)
Jeremy Friesner,

15

È semplicemente una dichiarazione di funzione che dichiara adi essere una funzione che restituisce Ae accetta un parametro di tipo senza nome B.

È valido perché le definizioni delle funzioni invece delle definizioni delle funzioni sono consentite all'interno delle definizioni delle funzioni.


13

Questo problema è noto come l' analisi più irritante . La riga A a(B);può essere interpretata come la dichiarazione di una funzione denominata che arestituisce un oggetto di tipo Ae accetta un parametro di tipo senza nome B.

Un modo per evitare questo problema è usare la sintassi di inizializzazione uniforme introdotta in C ++ 11, che consiste nell'uso delle parentesi graffe anziché della parentesi: A a{B};restituisce un errore. La riga viene ora interpretata come una dichiarazione di variabile inizializzata con B, che è un tipo anziché un valore.

Ecco maggiori informazioni:

La più fastidiosa analisi: come individuarla e risolverla rapidamente


12
Non penso che questo dovrebbe essere chiamato " analisi più irritante ". È solo una normale dichiarazione di funzione come esiste anche in C. Non è necessaria alcuna risoluzione di ambiguità perché la riga può essere solo una dichiarazione di funzione, nient'altro. Guarda il tuo link. Gli esempi sono tutti diversi da questo.
Walnut

3
Sebbene sia vero, è correlato all'analisi più irritante. È solo che questo includeva anche un refuso in cui un nome di tipo veniva usato da solo invece di una variabile o una chiamata del costruttore, come probabilmente era l'intento originale.
Miral

1
Sì, "Most Vexing Parse" è una risposta utile in questo caso, anche se il caso reale nella domanda è solo "Parse Vexing Parse".
jpa,

1
@wlanut: le strutture vuote struct A { };non sono valide nello standard C, anche se alcuni compilatori lo consentono. Lascia cadere le parentesi graffe e non ci sarebbe un problema lì. Inoltre, in C, la dichiarazione o la definizione struct Anon creano un nome di tipo A(è necessario structaggiungere un prefisso o aggiungere typedef struct A A;da qualche parte prima che Avenga utilizzato senza il structprefisso). Anche in C, non esiste un analisi alternativa alla dichiarazione di funzione: usare type name(...);semplicemente non può mai essere una definizione variabile; è sempre una dichiarazione di funzione (o non valida). Il codice nella domanda non è valido in C.
Jonathan Leffler il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.