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?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
discape
  • 337
  • 1
  • 15
  • 8
    `y = 5` _is_ an expression, and it has value `5`. Why do you think it isn't? – Useless Oct 18 '19 at 09:21
  • 2
    With regards to the missing `return` of `main`, see [this question](https://stackoverflow.com/questions/19293642/c-why-main-works-with-no-return-value). – walnut Oct 18 '19 at 09:22
  • 3
    Better yet, remove the second question. One *single* question per question is the preferred model on Stack Overflow. – StoryTeller - Unslander Monica Oct 18 '19 at 09:24
  • 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++. – user7860670 Oct 18 '19 at 09:40

4 Answers4

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.

lubgr
  • 37,368
  • 3
  • 66
  • 117
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
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
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;
RHertel
  • 23,412
  • 5
  • 38
  • 64
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.

Xatyrian
  • 1,364
  • 8
  • 26