Почну з вашого останнього запитання
Крім того, чому компілятор чи IDE не скаржаться на те, що main () не повертає Int?
Відповідно до стандарту C ++ (основна функція 6.6.1)
5 Оператор повернення в основному має наслідком залишення основної функції (знищення будь-яких об'єктів з автоматичною тривалістю зберігання) та виклик std :: exit із значенням повернення. Якщо управління відтікає від кінця з'єднання-оператора main, ефект еквівалентний поверненню з операндом 0 (див. Також 18.3).
І стосовно цього питання
Як це можливо, оскільки y = 5 не є виразом, який можна обчислити?
Зі стандарту C ++ (8.18 Оператори присвоєння та призначення складових)
1 Оператор присвоєння (=) та оператори присвоєння складної групи всі групи справа наліво. Усі вимагають модифікованого значення lvalue як їх лівий операнд і повертають lvalue, що відноситься до лівого операнду.
Розгорнути цю декларацію
int x{ y = 5 };
можна рівномірно розділити на два твердження
y = 5;
int x{ y };
Більше того, в C ++ ви навіть можете зробити посилання на змінну y наступним чином
int &x{ y = 5 };
Ось показова програма
#include <iostream>
int main()
{
int y;
int &x{ y = 5 };
std::cout << "y = " << y << '\n';
x = 10;
std::cout << "y = " << y << '\n';
}
Його вихід є
y = 5
y = 10
Ви можете цю декларацію
int x{ y = 5 };
переписати також як
int x = { y = 5 };
Однак врахуйте, що між цими (виглядаючи аналогічно вищезазначеним деклараціям) двома деклараціями є різниця.
auto x{ y = 5 };
і
auto x = { y = 5 };
У першій декларації змінна x
має тип int
. У другій декларації змінна x
має тип std::initializer_list<int>
.
Щоб зробити різницю більш помітною, подивіться, як виводяться значення об'єктів.
#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;
}
Вихід програми є
x1 = 5
*x2.begin()= 10
y = 10
y = 5
- це вираз, і воно має значення5
. Чому ти вважаєш, що це не так?