1
#include <iostream>

int main() {
    int x, y;
    x, y = 10, 20;
    std::cout << x;
    return 0;
}

I expect 10 as output but 16 is coming. What's the reason? Can someone explain that behavior in c++ please?

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
kNIG132103
  • 75
  • 6
  • 6
    `x,y=10,20;` doesn't do what you think it does! Who taught you to do initialization in that way?? You're probably better served reading a [good book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list), rather than asking about basics here. – πάντα ῥεῖ Oct 05 '21 at 17:08
  • [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – Filburt Oct 05 '21 at 17:08
  • 3
    This is very related https://stackoverflow.com/questions/35877190 but there's an exact dupe of your question as well. I'll see if I can track it down. – cigien Oct 05 '21 at 17:09
  • 1
    @Filburt In all fairness, the debugger will just step over this line, and show the new variable values, without explaining what's going on. You either know this language feature or your don't. – HolyBlackCat Oct 05 '21 at 17:09
  • 2
    You want either `int x, y; std::tie(x, y) = std::forward_as_tuple(10, 20);`, or `auto [x, y] = std::forward_as_tuple(10, 20);`. – HolyBlackCat Oct 05 '21 at 17:12
  • 2
    (that is the second example, the one with `auto [...]`) – HolyBlackCat Oct 05 '21 at 17:14
  • 1
    Let's reopen this since there are some interesting ways from C++17 onwards of achieving this. – Bathsheba Oct 05 '21 at 17:15
  • @HolyBlackCat Using a debugger and inspecting the runtime value will take you one step ahead in that you discover the value of `x` and how it is different from what you'd expect. This is about learning to use a debugger as early as possible instead of just looking at output or a runtime error. – Filburt Oct 05 '21 at 21:43
  • @kNIG132103 1st and only rule: Don't call me "sir"! – πάντα ῥεῖ Oct 06 '21 at 11:56
  • 1
    @kNIG132103 Basically your code invokes _undefined behavior_, because you're accessing an uninitialized variable for output. Undefined behavior is undefined, and generally cannot be reproduced, thus I am voting your question to be closed for that reason now. – πάντα ῥεῖ Oct 06 '21 at 12:28

2 Answers2

7

x, y = 10, 20; is interpreted as (x), (y = 10), (20);.

The three expressions are just executed sequentally. x and 20 do nothing, and y = 10 does what it says on the tin.

x remains uninitialzied, and reading it is undefined behavior.


There is a way to do what you want, but it's a part of the standard library (#include <tuple>), not built into the language.

It's also quite verbose, so it might be a better idea to just assign to each variable separately.

If you want to assign to existing variables:

int x, y;
std::tie(x, y) = std::forward_as_tuple(10, 20);

Or, if you want to create new variables:

auto [x, y] = std::forward_as_tuple(10, 20);

(the auto [...] syntax is called a structured binding, and is available since C++17)


If the rhs are variables (lvalues), you can use less verbose std::tie instead of std::forward_as_tuple.

In some cases you need std::tuple instead of std::forward_as_tuple, it will copy/move the rhs before assigning them. This is required e.g. when returning the tuple from a function, or if you want to do std::tie(x, y) = std::tuple(y, x);.

You can also use std::tuple instead of std::forward_as_tuple for brevity, is the rhs is inexpensive to copy/move.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
6

It seems that you want to do in C++ what is ok in languages like Python. This line

x, y = 10, 20

in Python will do what you want: it will initialize x to 10 and y to 20. But in C++ it does something very different. The comma operator in C++ works as follows: given E1, E2, E3; expression C++ will evaluate E1 and discard its result, evaluate E2 and discard its result, evalute E3 and return it as a value of the entire expression (in your case it will be discarded as well, since there is no left side).

And so in C++ the

x, y = 10, 20

expression does what follows: reads x, sets y = 10 and reads 20. Therefore your

std::cout << x;

line has Undefined Behaviour, you print an uninitialized variable (well, you already have UB in the expression itself as well). This means that anything can happen: x can be anything, including 16 in your case, but also your program may simply crash.

Note that C++ does have tools to emulate this "Python like behaviour" (see HolyBlackCat's answer) but I suggest simply doing

int x = 10;
int y = 20;

Not a one-liner, but easy to read and understand.

freakish
  • 54,167
  • 9
  • 132
  • 169