Por que é possível int x {y = 5}?

10
int main() {
    int y;
    int x{ y = 5 };
    //x is 5
}

Como isso é possível, pois y = 5 não é uma expressão calculável?

Além disso, por que o compilador ou o IDE não reclama que main () não retorna um int?

counterstriker0
fonte
8
y = 5 é uma expressão e tem valor 5. Por que você acha que não é?
Inútil
2
Com relação à falta returnde main, veja esta pergunta .
Walnut
3
Melhor ainda, remova a segunda pergunta. Uma única pergunta por pergunta é o modelo preferido no Stack Overflow.
StoryTeller - Unslander Monica
Talvez você deva redefinir a pergunta para por que y = 5produz 5 aqui. A possibilidade de os operadores de atribuição retornarem algo é realmente um recurso bizarro do C / C ++.
user7860670

Respostas:

11

Vou começar com a sua última pergunta

Além disso, por que o compilador ou o IDE não reclama de main () não retornando um int?

De acordo com o padrão C ++ (função principal 6.6.1)

5 Uma declaração de retorno em main tem o efeito de deixar a função principal (destruindo qualquer objeto com duração de armazenamento automático) e chamar std :: exit com o valor de retorno como argumento. Se o controle sair do final da instrução composta de main, o efeito será equivalente a um retorno com o operando 0 (consulte também 18.3).

E em relação a esta pergunta

Como isso é possível, pois y = 5 não é uma expressão calculável?

No padrão C ++ (operadores de atribuição 8.18 e atribuição composta)

1 O operador de atribuição (=) e os operadores de atribuição composta todos agrupam da direita para a esquerda. Todos exigem um lvalue modificável como seu operando esquerdo e retornam um lvalue referente ao operando esquerdo.

Sp esta declaração

int x{ y = 5 };

pode ser dividido em duas instruções

y = 5;
int x{ y };

Além disso, em C ++, você pode até fazer uma referência à variável y da seguinte maneira

int &x{ y = 5 };

Aqui está um programa demonstrativo

#include <iostream>

int main() 
{
    int y;
    int &x{ y = 5 };    

    std::cout << "y = " << y << '\n';

    x = 10;

    std::cout << "y = " << y << '\n';
}

Sua saída é

y = 5
y = 10

Você pode esta declaração

int x{ y = 5 };

reescrever também como

int x = { y = 5 };

No entanto, leve em consideração que há uma diferença entre essas duas declarações (semelhante à das declarações acima).

auto x{ y = 5 };

e

auto x = { y = 5 };

Na primeira declaração a variável xtem o tipo int. Na segunda declaração a variável xtem o tipo std::initializer_list<int>.

Para tornar a diferença mais visível, veja como os valores dos objetos são gerados.

#include <iostream>

int main() 
{
    int y;
    auto x1 { y = 5 };  

    std::cout << "x1 = " << x1 << '\n';

    auto x2 = { y = 10 };   

    std::cout << "*x2.begin()= " << *x2.begin() << '\n';

    std::cout << "y = " << y << '\n';

    return 0;
}

A saída do programa é

x1 = 5
*x2.begin()= 10
y = 10
Vlad de Moscou
fonte
16

Como isso é possível, pois y = 5 não é uma expressão calculável?

É uma atribuição, e as atribuições geram valores, ou seja, o "tipo não qualificado de cv do operando esquerdo", consulte [expr.ass / 3] . Daí y = 5resulta em y, que é 5, que é usado para inicializarx .

Com relação à sua segunda pergunta, consulte cppreference em main (ou [basic.start.main / 5] ):

O corpo da função principal não precisa conter a returninstrução: se o controle chega ao final da função principal sem encontrar uma returninstrução, o efeito é o da execução return 0;.

Portanto, o compilador ou o IDE avisando sobre uma returndeclaração ausente no final de mainseria totalmente errado. É certo que o fato de que você sempre deve returnobjetos de voidfunções não executadasmain é meio que ... bem, por razões históricas, eu acho.

lubgr
fonte
2
Uma expressão pode resultar em um valor, mas apenas uma função pode return. -pedantic
Inútil
Eu acho que isso int x {y = 5}; instrução não é válida em c
bhura 18/10/19
@bhura - a pergunta é sobre C ++, não C
StoryTeller - Unslander Monica
Talvez valha a pena mencionar que, mesmo que não seja obrigatório, ainda assim retornar um valor de main geralmente é considerado uma boa prática?
Aconcagua
4

Os operator=()resultados em um valor, que é o valor atribuído à variável. Por esse motivo, é possível encadear atribuições como esta:

int x, y, z;
x = y = z = 1;
RHertel
fonte
A expressão de atribuição tem um valor . Funções têm valores de retorno; expressões não.
Pete Becker
3

Se você der uma olhada na documentação sobre cppreference , verá queoperator=() retornará uma referência ao objeto que foi atribuído. Portanto, uma atribuição pode ser usada como uma expressão que retorna o objeto que foi atribuído.

Então, é apenas uma tarefa normal com aparelho.

Xatyrian
fonte