Eu não entendo por que isso compila


80

Certamente estou perdendo alguma coisa, mas não entendo por que isso compila (com g ++ e clang ++):

struct A
{
};
struct B
{
};

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

Primeiro de tudo, Bé um tipo ... não um valor. Como devo interpretar esse código?


37
Isso é conhecido como o Analisador mais irritante
alter igel

8
@alterigel É mesmo? Nesse caso, não há ambiguidade. Só pode ser uma declaração de função. Não é o A a(B());que poderia ser uma definição variável ou declaração de função.
Walnut3

8
Você ficaria surpreso ao saber que struct A{}; int main() { A(foo); } compila como está , mesmo fooque não cite nada.
precisa saber é

20
@alterigel - esta não é a análise mais irritante. Veja os exemplos na página que você vinculou. Isto é simplesmente uma declaração de função.
Pete Becker

3
@PeteBecker, talvez seja melhor explicar por que isso não é MVP, em vez de apenas afirmar que não é, o que acredito que a noz já fez acima.
precisa saber é o seguinte

Respostas:


84

É interpretada como a declaração de uma função chamada a, que recebe um argumento do tipo Be retorna A.


5
E é por isso que é Most e Vexing. A solução: (não que isso realmente resolve nada, uma vez que expõe a má construção)A a{B};
user4581301

23
@ user4581301 - é não o mais parse irritante. É simplesmente uma declaração de função.
Pete Becker

23
Acontece que é apenas uma análise principalmente irritante ...
MooseBoys 4/19

11
A parte mais estranha sobre ele é que C ++ não permite funções aninhadas, mas não permitem declarações dentro de uma função.
The_Sympathizer

6
Parece uma boa motivação para adicionar suporte a funções aninhadas no C ++; Não só eles ser útil, eles transformar esta verruga estranho em um projeto razoável :)
Jeremy Friesner

15

É simplesmente uma declaração de função que declara aser uma função retornando Ae recebendo um parâmetro do tipo sem nome B.

É válido porque declarações de função, em oposição às definições de função, são permitidas nas definições de função.


13

Esse problema é conhecido como a análise mais irritante . A linha A a(B);pode ser interpretada como a declaração de uma função denominadaa retornando um objeto do tipo Ae assumindo um parâmetro do tipo sem nome B.

Uma maneira de evitar esse problema é usar a inicialização uniforme sintaxe de introduzida no C ++ 11, que consiste em usar chaves em vez de parênteses: A a{B};retorna um erro. A linha agora é interpretada como uma declaração de variável inicializada com B, que é um tipo em vez de um valor.

Aqui estão mais informações:

A análise mais irritante: como localizá-lo e corrigi-lo rapidamente


12
Eu não acho que isso deva ser chamado de " análise mais irritante ". É apenas uma declaração de função usual, como também existe em C. Não há resolução de ambiguidade necessária porque a linha pode ser apenas uma declaração de função, nada mais. Olhe para o seu link. Os exemplos são todos diferentes disso.
Walnut #

3
Embora isso seja verdade, está relacionado à análise mais irritante. É que isso também incluiu um erro de digitação em que um nome de tipo foi usado sozinho em vez de uma variável ou uma chamada de construtor, como provavelmente era a intenção original.
Miral

11
Sim, "Most Vexing Parse" é uma resposta útil nesse caso, mesmo que o caso real da pergunta seja apenas "Slightly Vexing Parse".
jpa

11
@ wlanut: As estruturas vazias struct A { };não são válidas no padrão C, mesmo que alguns compiladores permitam. Solte o aparelho e não haveria problema lá. Além disso, em C, declarar ou definir struct Anão cria um nome de tipo A(você deve prefixá-lo structou incluir em typedef struct A A;algum lugar antes de Aser usado sem o structprefixo). Também em C, não há análise alternativa para a declaração da função - o uso type name(...);simplesmente nunca pode ser uma definição de variável; é sempre uma declaração de função (ou inválida). O código na pergunta não é válido em C. #
Jonathan Leffler
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.