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 x
ma typ int
. W drugiej deklaracji zmienna x
ma 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
y = 5
jest wyrażeniem i ma wartość5
. Jak myślisz, dlaczego tak nie jest?