Why is int x{ y = 5 } possible?
Asked Answered
D

4

10
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?

Dude answered 18/10, 2019 at 9:17 Comment(4)
y = 5 is an expression, and it has value 5. Why do you think it isn't?Vashtee
With regards to the missing return of main, see this question.Proboscidean
Better yet, remove the second question. One single question per question is the preferred model on Stack Overflow.Mispickel
Perhaps you should redefine question to why y = 5 yields 5 here. Possibility of assignment operators to return something is indeed a bizarre feature of C/C++.Upwards
B
11

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
Barr answered 18/10, 2019 at 9:38 Comment(0)
H
16

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

It is an assignment, and assignments yield values, i.e. 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.

Height answered 18/10, 2019 at 9:21 Comment(4)
An expression can result in a value, but only a function can return one. -pedanticVashtee
I think this int x{y=5}; statement is not valid in cCassatt
@bhura - the question is about C++, not CMispickel
Perhaps worth to mention that, even if not required, still returning a value from main usually is considered good practice?Blackcock
B
11

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
Barr answered 18/10, 2019 at 9:38 Comment(0)
A
4

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;
Argentous answered 18/10, 2019 at 9:24 Comment(1)
The assignment expression has a value. Functions have return values; expressions do not.Geanticline
T
3

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.

Trace answered 18/10, 2019 at 9:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.