Dlaczego int x {y = 5} jest możliwe?

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

Jak to możliwe, skoro y = 5 nie jest wyrażeniem obliczalnym?

Ponadto, dlaczego kompilator lub IDE nie narzeka na to, że main () nie zwraca int?

counterstriker0
źródło
8
y = 5 jest wyrażeniem i ma wartość 5. Jak myślisz, dlaczego tak nie jest?
Bezużyteczne
2
W odniesieniu do brakujących returnz mainpatrz na to pytanie .
orzech
3
Jeszcze lepiej, usuń drugie pytanie. Jeden pojedynczy pytanie za pytaniem jest preferowanym modelem na przepełnienie stosu.
StoryTeller - Unslander Monica
Być może powinieneś ponownie zdefiniować pytanie, dlaczego y = 5daje 5 tutaj. Możliwość zwrócenia czegoś przez operatorów przypisań jest rzeczywiście dziwną cechą C / C ++.
user7860670,

Odpowiedzi:

11

Zacznę od twojego ostatniego pytania

Ponadto, dlaczego kompilator lub IDE nie narzeka na to, że main () nie zwraca int?

Zgodnie ze standardem C ++ (główna funkcja 6.6.1)

5 Instrukcja return w main powoduje pozostawienie funkcji main (zniszczenie dowolnych obiektów z automatycznym czasem przechowywania) i wywołanie std :: exit z argumentem zwracanej wartości. Jeśli kontrola wypływa z końca instrukcji złożonej main, efekt jest równoważny zwrotowi z operandem 0 (patrz także 18.3).

I w odniesieniu do tego pytania

Jak to możliwe, skoro y = 5 nie jest wyrażeniem obliczalnym?

Ze standardu C ++ (operatory przypisania i przypisania złożonego 8.18)

1 Operator przypisania (=) i złożone operatory przypisania wszystkie grupy od prawej do lewej. Wszystkie wymagają modyfikowalnej wartości jako lewego operandu i zwracają wartość odnoszącą się do lewego operandu.

Sp to oświadczenie

int x{ y = 5 };

można równo podzielić na dwie instrukcje

y = 5;
int x{ y };

Ponadto w C ++ możesz nawet odwołać się do zmiennej y w następujący sposób

int &x{ y = 5 };

Oto program demonstracyjny

#include <iostream>

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

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

    x = 10;

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

Jego wydajność to

y = 5
y = 10

Możesz tę deklarację

int x{ y = 5 };

przepisz również jak

int x = { y = 5 };

Należy jednak wziąć pod uwagę, że istnieje różnica między nimi (wyglądającymi podobnie jak powyższe deklaracje) dwie deklaracje.

auto x{ y = 5 };

i

auto x = { y = 5 };

W pierwszej deklaracji zmienna xma typ int. W drugiej deklaracji zmienna xma typ std::initializer_list<int>.

Aby różnica była bardziej widoczna, zobacz, w jaki sposób generowane są wartości obiektów.

#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;
}

Wyjście programu to

x1 = 5
*x2.begin()= 10
y = 10
Vlad z Moskwy
źródło
16

Jak to możliwe, skoro y = 5 nie jest wyrażeniem obliczalnym?

Jest to przypisanie, a przypisania dają wartości, tzn. „Lewy operand niekwalifikowany cv”, patrz [expr.ass / 3] . Stąd też y = 5powoduje y, która jest 5, co jest wykorzystywane do inicjacji x.

W odniesieniu do drugiego pytania zobacz cppreference na main (lub [basic.start.main / 5] ):

Treść funkcji głównej nie musi zawierać returninstrukcji: jeśli kontrola osiągnie koniec main bez napotkania returninstrukcji, efektem będzie wykonanie return 0;.

Dlatego kompilator lub IDE ostrzegający o brakującym returnwyrażeniu na końcu mainbyłoby po prostu błędne. Trzeba przyznać, że fakt, że zawsze powinieneś returnsprzeciwić się wykonywaniu voidfunkcji niemain jest… no cóż, chyba z powodów historycznych.

lubgr
źródło
2
Wyrażenie może dawać wartość, ale tylko jedna funkcja może return. -pedantic
Bezużyteczny
Myślę, że to int x {y = 5}; instrukcja nie jest ważna w c
bhura
@bhura - pytanie dotyczy C ++, a nie C
StoryTeller - Unslander Monica
Być może warto wspomnieć, że nawet jeśli nie jest to wymagane, nadal zwracanie wartości z głównego jest zwykle uważane za dobrą praktykę?
Aconcagua,
4

Te operator=()wyniki w wartości, która jest wartość przypisana do zmiennej. Z tego powodu możliwe jest połączenie zadań w następujący sposób:

int x, y, z;
x = y = z = 1;
RHertel
źródło
Przypisanie ma wartość . Funkcje mają zwracane wartości; wyrażenia nie.
Pete Becker
3

Jeśli spojrzysz na dokumentację dotyczącą cppreferencji , zobaczysz, że operator=()zwraca odwołanie do obiektu, który został przypisany. Dlatego przypisanie może być użyte jako wyrażenie zwracające przypisany obiekt.

To normalne zadanie z nawiasami klamrowymi.

Xatyrian
źródło