C++ Multi-Assign Python feature - c++

I am trying to learn C++. While experimenting, I typed in the following code, not expecting it to work, but hoping it would:
int one = 1, two = 2;
one, two = two, one;
cout << "one = " << one << "\n";
cout << "two = " << two << "\n";
I was encouraged by the fact that the compiler didn't complain, because this is one of the main features that I love about python that most every programming language I've ever learned does not match - the ability to evaluate multiple expressions before assigning the results WITHOUT using a temporary variable. However, I found when I ran it that this code seems to be ineffectual.
After playing around a bit, I discovered that the variable two is actually being set - so, if I ran this code:
one, two = 3, 4;
two would be equal to 3, but one would be unchanged. And so my question is, what exactly is the compiler doing in this statement? I can't for the life of me figure it out.
Thanks,
Brandon

Multi-assignment python style is not supported in C++, the comma operator does not do what you intend: http://en.wikipedia.org/wiki/Comma_operator
If you were assigning the same value to both one and two then you could do
one = two = 3;
but in your case you are not so they must be on separate lines:
one = 3;
two = 4;
if you wanted to swap the values then you must use a temporary third variable:
int temp = one;
one = two;
two = temp;
If we consider the following:
one, two = 3, 4;
the simple case is 3 ,4; here the 4 will be discarded so only 3 will remain, you then have
one, two = 3;
Now you have the assignment operator = which has higher precedence than the , operator so irrespective of what happens with one, two the two = 3; is evaluated first before one, two resulting in:
two = 3;

First, = operator has higher precedence than , thus both lines below are equivalent:
(one), (two = 3), (4);
one, two = 3, 4;
Second, the comma operator is a way to group multiple statements, but only express the value of the last one, so:
int a, b;
a = (b = 5, b*b);
cout << a << '\n';
Would print 25. Hope to have enlightened you on what the compiler was doing.

In C++11 there is std::tie.
Example:
#include <tuple>
#include <iostream>
int main()
{
int a, b;
std::tie(a, b) = std::make_tuple(1, 2);
std::cout << a << ", " << b;
}
Output: 1, 2. std::tie() creates tuple of references - and std::tuple has overload for operator=().
I know it's not same syntax as the one used in Python, but it's functionally the same and you may want to use it.

Related

Why should you include more than one value in a return statement?

I've seen instances where someone would use return statements with multiple values. For example: return 8, 10, 6; As far as I know, only one of these values will actually be returned. What is the benefit of using return this way?
Specifically, this question appears on my homework.
The statement: return 2 * 3 + 1, 1 + 5; returns the value ____.
I know it would always return 6, so why would I ever write it like this?
Forgive me if this is a simple question. I am still somewhat new to programming.
The statement return 2 * 3 + 1, 1 + 5; returns the value 6.
This the trick of comma operator in C++. You can read more about it here:
https://en.cppreference.com/w/cpp/language/operator_other
A comma operator is basically a list of expressions separated by commas, they will be evaluated from left to right, and the result of the last item will be treated as the result of the whole comma operator.
Here is a simple example demonstrating how comma operator works.
int foo() {
int i = 1;
return i += 2, i++, i + 5; // This is a comma operator with three items
// i += 2 will be evaluated first, then i == 3
// i++ will be evaluated second, then i == 4
// i + 5 will be evaluate last, and the result is 9
// the result of the last item is returned by the return statement
}
int main() {
std::cout << foo();
return 0;
}
This code prints 9.
When you do this you are avoiding using math in your function block and this make your function like working 3 time and result would be the one you want

Why this is happening in the following code?

I am running this c++ program for swapping two numbers using g++ compiler in ubuntu.
int a = 6, b = 9;
a = a ^ b ^ (b = a);
cout << a << " " << b;
and I am getting this output 9 6. Here first b is processed (old value of b that is 9) before processing b=a part.
But when I run this program
a = a ^ b + (b = a);
cout << a << " " << b;
I get 10 6 as output. It means here b = a part is processed first therefore the value of every b is now 6 hence it is giving output 10 6.
can anybody explain why it is happening so?
a = a ^ b ^ (b = a) involves undefined behavior because the order of evaluation is not specified. If all you want is to swap two integers, use std::swap:
using std::swap;
int a = 6, b = 9;
swap(a, b);
The behaviour of your code is undefined! (b=a) writes to b. There are also reads of b in that same expression a^b^(b=a), and there are no sequencing points in that expression either.
The language does not define the behaviour of a read and write of the same variable in an unsequenced step.
Note for the avoidance of doubt, the parentheses do not specify an order of evaluation, but rather grouping.
P.S. XOR swap is silly, and probably slower than std::swap.

Compound Assignment (Multiply)

I recently learn the basic of C++. And i found something that i didn't get the idea. Here is the program that make me a little confuse.
#include <iostream>
using namespace std;
int main()
{
int m = 4, n;
n=++m*--m;
cout <<"m="<<m<<" and n="<<n<<"\n;
return 0;
}
And the output is m=4 and n=16.
I thought that
m=4, so ++m is 5, and --m will be 4,
then n= 5*4= 20.
Hence, the m=4 and n=20.
I think mine is false. So i need a help. Thank you.
The operands of * are unsequenced relative to each other. This means that not only may they be evaluated in any order; but if each operand contains multiple sub-steps, the sub-steps of one operand might be interleaved with those of the other operand.
An example of this might be (f() + g()) * (h() + i()) . The four functions could be called in any order -- it is not required that f and g are called together, etc.
Back to your example, the following two sub-steps are unsequenced relative to each other:
writing the new value to m, as part of ++m
reading m, as part of --m
When there are two unsequenced operations on the same variable (and at least one of them is a write), it is undefined behaviour which means anything can happen (including unexpected results).
This:
n=++m*--m;
is bad code. Replace it with something clear, such as:
n = (m + 1) * (m - 1);
The original code, for complicated reasons, may not do what you expect, so it's better not to write such code in the first place. If you want to know more about the nitty gritty details of why this is, see here: Undefined behavior and sequence points
++m means "increment m then use its value" The current call with have (m + 1) as value.
m-- means "use the value of m, then decrement it" The current call with have the original value of m, and subsequent calls will have (m - 1) as value
If that makes it any clearer for you, you can also rewrite it as:
int m = 4, n;
n = (m = (m + 1)) * (m = (m - 1));
I am pretty positive the operation occurs before the increment. That is why that is happening. If you break it down like this, it should work.
The answer should be 15 because 4 + 1 is 5 and 4 - 3 is 3, thus 5 * 3 is 15. See below
int main()
{
int m = 4, n;
int g;
n = (m+1) * (m-1);
std::cout << "m=" << m << " and n=" << n << "\n" ;
std::cin >> g;
return 0;
}

Compare a value with all array elements in one statement

For example:
if (value == array[size]) //if the value (unique) is present in an array then do something
can this be done in one statement without having to call a function or a basic for loop statement?
std::find can do it in one statement, but it's not as trivial as other languages :(
int array[10];
if (array + 10 != find(array, array + 10, 7)) {
cout << "Array contains 7!";
}
Or with std::count:
if (int n = count(array, array + 10, 7)) {
cout << "Array contains " << n << " 7s!";
}
Depending on the problem, you might want to use a set. It has a member function called count() that tells you if something is in the set:
if(myset.count(value) > 0){
doThings();
}
There is no built-in operator to do such a thing.
There are numerous ways to perform the test as what appears to be a single statement from the outside. And some of which use parts already provided by the standard library, so that you wouldn't have to write much code yourself. However, they will inevitably use some form of function call and/or loop at some point which you already ruled out.
So given the restrictions in your question: No, there isn't any way.

Effect of using a comma instead of a semi-colon in C and C++

I've noticed on a number of occasions when refactoring various pieces of C and C++ code that a comma is used rather than a semi-colon to seperate statements. Something like this;
int a = 0, b = 0;
a = 5, b = 5;
Where I would have expected
int a = 0, b = 0;
a = 5; b = 5;
I know that C and C++ allow use of commas to seperate statements (notably loop headers), but what is the difference if any between these two pieces of code? My guess is that the comma has been left in as the result of cut & pasting, but is it a bug and does it effect execution?
It doesn't make a difference in the code you posted. In general, the comma separates expressions just like a semicolon, however, if you take the whole as an expression, then the comma operator means that the expression evaluates to the last argument.
Here's an example:
b = (3, 5);
Will evaluate 3, then 5 and assign the latter to b. So b = 5. Note that the brackets are important here:
b = 3, 5;
Will evaluate b = 3, then 5 and the result of the whole expression is 5, nevertheless b == 3.
The comma operator is especially helpful in for-loops when your iterator code is not a simple i++, but you need to do multiple commands. In that case a semicolon doesn't work well with the for-loop syntax.
The comma is a operator that returns a value which is always the 2nd (right) argument while a semicolon just ends statements. That allows the comma operator to be used inside other statements or to concatenate multiple statements to appear as one.
Here the function f(x) gets called and then x > y is evaluated for the if statement.
if( y = f(x), x > y )
An example when it's used just to avoid a the need for block
if( ... )
x = 2, y = 3;
if( ... ) {
x = 2;
y = 3;
}
The comma operator evaluates all operands from left to right, and the result is the value of the last operand.
It is mostly useful in for-loops if you want to do multiple actions in the "increment" part, e.g (reversing a string)
for (int lower = 0, upper = s.size() - 1; lower < upper; ++lower, --upper)
std::swap(s[lower], s[upper]);
Another example, where it might be an option (finding all occurrences in a string):
#include <string>
#include <iostream>
int main()
{
std::string s("abracadabra");
size_t search_position = 0;
size_t position = 0;
while (position = s.find('a', search_position), position != std::string::npos) {
std::cout << position << '\n';
search_position = position + 1;
}
}
In particular, logical and cannot be used for this condition, since both zero and non-zero can mean that the character was found in the string. With comma, on the other hand, position = s.find() is called each time when the condition is evaluated, but the result of this part of the condition is just ignored.
Naturally there are other ways to write the loop:
while ((position = s.find('a', search_position)) != std::string::npos)
or just
while (true) {
position = s.find('a', search_position);
if (position == std::string::npos)
break;
...
}
As Frank mentioned, how the comma operator is used in your example doesn't cause a bug. The comma operator can be confusing for several reasons:
it's not seen too often because it's only necessary in some special situations
there are several other syntactic uses of the comma that may look like a comma operator - but they aren't (the commas used to separate function parameters/arguments, the commas used to separate variable declarations or initializers)
Since it's confusing and often unnecessary, the comma operator should be avoided except for some very specific situations:
it can be useful to perform multiple operation in one or more of a for statement's controlling expressions
it can be used in preprocessor macros to evaluate more than one expression in a single statement. This is usually done to allow a macros to do more than one thing and still be a a single expression so the macro will 'fit' in places that only allow an expression.
The comma operator is a hackish operator pretty much by definition - it's to hack in 2 things where only one is allowed. It's almost always ugly, but sometimes that's all you've got. And that's the only time you should use it - if you have another option, don't use the comma operator.
Off the top of my head I can't think of too many other reasons to use the operator, since you can get a similar effect by evaluating the expressions in separate statements in most other situations (though I'm sure that someone will comment on a another use that I've overlooked).
One usage would be in code golfing:
if (x == 1) y = 2, z = 3;
if (x == 1) { y = 2; z = 3; }
The first line is shorter, but that looks too confusing to use in regular development.