简体   繁体   中英

Why is int x{ y = 5 } possible?

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

How is this possible, since y = 5 is not a calculable expression?

Also, why doesn't the compiler or IDE complain about main() not returning an int?

How is this possible, since y = 5 is not a calculable expression?

It is an assignment, and assignments yield values, ie the "cv-unqualified type of the left operand", see [expr.ass/3] . Hence y = 5 results in y , which is 5 , which is used to initialize x .

With respect to your second question, see cppreference on main (or [basic.start.main/5] ):

The body of the main function does not need to contain the return statement: if control reaches the end of main without encountering a return statement, the effect is that of executing return 0; .

Hence, compiler or IDE warning you about a missing return statement at the end of main would be plain wrong. Admittedly, the fact that you should always return objects from non- void functions execpt main is kind of... well, for historical reason I guess.

The operator=() results in a value, which is the value assigned to the variable. Because of this, it is possible to chain assignments like this:

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

I will start from your last question

Also, why doesn't the compiler or IDE complain about main() not returning an int?

According to the C++ Standard (6.6.1 main function)

5 A return statement in main has the effect of leaving the main function (destroying any objects with automatic storage duration) and calling std::exit with the return value as the argument. If control flows off the end of the compound-statement of main, the effect is equivalent to a return with operand 0 (see also 18.3).

And relative to this question

How is this possible, since y = 5 is not a calculable expression?

From the C++ Standard (8.18 Assignment and compound assignment operators)

1 The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand and return an lvalue referring to the left operand.

Sp this declaration

int x{ y = 5 };

can be equivalently split into two statements

y = 5;
int x{ y };

Moreover in C++ you can even to make a reference to the variable y the following way

int &x{ y = 5 };

Here is a demonstrative program

#include <iostream>

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

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

    x = 10;

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

Its output is

y = 5
y = 10

You may this declaration

int x{ y = 5 };

rewrite also like

int x = { y = 5 };

However take into account that there is a difference between these (looking similarly as the above declarations) two declarations.

auto x{ y = 5 };

and

auto x = { y = 5 };

In the first declaration the variable x has the type int . In the second declaration the variable x has the type std::initializer_list<int> .

To make the difference more visible see how the values of the objects are outputted.

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

The program output is

x1 = 5
*x2.begin()= 10
y = 10

If you take a look at the documentation on cppreference , you'll see that operator=() return a reference to the object that was assigned. Therefore, a assignment can be used as an expression that returns the object that was assigned.

Then, it's just a normal assignment with braces.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM