Intencionalmente ou por acidente, você tem <<
no final da primeira linha de saída, onde você provavelmente quis dizer ;
. Então você essencialmente tem
cout << "2+3 = "; // this, of course, prints "2+3 = "
cout << cout; // this prints "1"
cout << 2 + 3; // this prints "5"
cout << endl; // this finishes the line
Portanto, a questão se resume a isso: por que cout << cout;
imprimir "1"
?
Isso acaba sendo, talvez surpreendentemente, sutil. std::cout
, por meio de sua classe base std::basic_ios
, fornece um certo operador de conversão de tipo que deve ser usado no contexto booleano, como em
while (cout) { PrintSomething(cout); }
Este é um exemplo muito ruim, pois é difícil fazer com que a saída falhe - mas std::basic_ios
na verdade é uma classe base para os fluxos de entrada e saída e, para entrada, faz muito mais sentido:
int value;
while (cin >> value) { DoSomethingWith(value); }
(sai do loop no final do fluxo ou quando os caracteres do fluxo não formam um número inteiro válido).
Agora, a definição exata desse operador de conversão mudou entre as versões C ++ 03 e C ++ 11 do padrão. Nas versões mais antigas, era operator void*() const;
(normalmente implementado como return fail() ? NULL : this;
), enquanto nas mais recentes era explicit operator bool() const;
(normalmente implementado simplesmente como return !fail();
). Ambas as declarações funcionam bem em um contexto booleano, mas se comportam de maneira diferente quando (mis) usadas fora desse contexto.
Em particular, sob as regras do C ++ 03, cout << cout
seria interpretado como cout << cout.operator void*()
e impresso algum endereço. Sob as regras do C ++ 11, cout << cout
não deve ser compilado, pois o operador é declarado explicit
e, portanto, não pode participar de conversões implícitas. Essa foi, de fato, a principal motivação para a mudança - impedindo a compilação de códigos sem sentido. Um compilador que esteja em conformidade com qualquer padrão não produzirá um programa que imprima "1"
.
Aparentemente, certas implementações em C ++ permitem misturar e combinar o compilador e a biblioteca de uma maneira que produza resultados não conformes (citando @StephanLechner: "Encontrei uma configuração no xcode que produz 1 e outra que gera um endereço: Language dialect c ++ 98 combinado com "Biblioteca padrão libc ++ (biblioteca padrão LLVM com suporte a c ++ 11)" gera 1, enquanto c ++ 98 combinado com libstdc (biblioteca padrão gnu c ++) gera um endereço; "). Você pode ter um compilador no estilo C ++ 03 que não entenda os explicit
operadores de conversão (novos no C ++ 11) combinados com uma biblioteca no estilo C ++ 11 que define a conversão como operator bool()
. Com essa mistura, torna-se possível cout << cout
interpretar como cout << cout.operator bool()
, que por sua vez é simples cout << true
e imprime "1"
.
;
- e - vírgula no final da primeira linha de saída, não<<
. Você não está imprimindo o que pensa que está imprimindo. Você está fazendocout << cout
, que imprime1
(usacout.operator bool()
, eu acho). Então5
(de2+3
) segue imediatamente, fazendo com que pareça o número quinze.