Чому можливий int x {y = 5}?


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

Як це можливо, оскільки y = 5 не є виразом, який можна обчислити?

Крім того, чому компілятор чи IDE не скаржаться на те, що main () не повертає Int?


8
y = 5 - це вираз, і воно має значення 5. Чому ти вважаєш, що це не так?
Марно

2
Що стосується зниклих без вести returnв mainсм це питання .
волоський горіх

3
А ще краще зняти друге питання. Одне окреме питання на запитання є кращою моделлю для переповнення стека.
StoryTeller - Невідповідна Моніка

Можливо, вам слід переосмислити питання, чому y = 5тут дається 5. Можливість операторів присвоєння повернути щось - це справді химерна особливість C / C ++.
користувач7860670

Відповіді:


11

Почну з вашого останнього запитання

Крім того, чому компілятор чи 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

16

Як це можливо, оскільки y = 5 не є виразом, який можна обчислити?

Це присвоєння і значення прибутків присвоєнь, тобто "cv-некваліфікований тип лівого операнда", див. [Expr.ass / 3] . Звідси y = 5випливає y, що є 5, що використовується для ініціалізації x.

Стосовно вашого другого питання див. Cppreference на main (або [basic.start.main / 5] ):

Основна функція не повинна містити returnоператор: якщо контроль доходить до кінця основного, не стикаючись із returnзаявою, ефект буде виконати return 0;.

Отже, компілятор або IDE попереджає вас про відсутність returnзаяви в кінці, mainбуло б явно неправильним. Правда, той факт , що ви повинні завжди returnоб'єкти з непредставлених voidфункцій execptmain начебто ... ну, з історичних причин , я думаю.


2
Вираз може призвести до значення, але лише функція може return. -педантик
Марно

Я думаю, що це int x {y = 5}; заява не дійсна в c
bhura

@bhura - питання стосується C ++, а не C
StoryTeller - Unslander Monica

Можливо, варто зазначити, що навіть якщо цього не потрібно, все-таки повернення значення з основного зазвичай вважається хорошою практикою?
Аконкагуа

4

В operator=()призводить до значення, яке є значення , присвоєне змінної. Через це можливо такі ланцюжки завдань:

int x, y, z;
x = y = z = 1;

Вираз присвоювання має значення . Функції мають зворотні значення; вирази ні.
Піт Бекер

3

Якщо ви подивитеся на документацію про cppreference , ви побачите, що operator=()повертає посилання на призначений об'єкт. Тому призначення може бути використане як вираз, який повертає об'єкт, який був призначений.

Тоді це просто звичайне завдання з брекетами.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.