So it seems like a lot of beginners tend to replace the comparison operator with the assignment operator. I understand the confusion, but what actually happens when you do this?
1 2 3 4 5 6
int c = 12;
int b = 7;
if(c == b)
//Do something....
//Ok now let's just replace the comparison with assignment
if(c = b)
//Do something...
The first part is obvious, we don't need to talk about that. But the second part:
First off, it assigns the value stored at b, into c. And then it performs the condition. So, this can boil down to if(12). A true is equal to one, and false is equal to zero (I believe, at least from C I think that's how it was). So unless you happen to assign a variable the value of 1, this type of situation will always be false? I seem to remember testing this before as I was helping a friend through a c++ class and he made this mistake, and the behavior was not as I expected. It actually went ahead and performed whatever it was, even though the value was not a 1. So what's the deal here? What exactly happens behind the scenes in these situations?
EDIT:
I guess I just found out that if you put a line of ----- in a code block here, it separates it all weird like. Interesting.
#include <iostream>
int main()
{
struct A
{
A& operator= ( const A& that )
{ std::cout << "assign one object of type A to another\n" ; return *this ; }
booloperator== ( const A& that ) const
{ std::cout << "compare equivalence of two object of type A\n" ; returntrue ; }
operatorbool () const
{ std::cout << "convert an object of type A to bool\n" ; returntrue ; }
};
A x, y ;
if( x == y ) ;
// prints: compare equivalence of two object of type A
if( x = y ) ;
// prints: assign one object of type A to another
// prints: convert an object of type A to bool
}
Sure, a reference is just an alias, but it's an alias that always 'refers' to the object it is representing. Saying this:
1 2 3
int z = 9;
int &a = z;
int b = a;
is correct, because using 'a' anywhere will always refer directly to the value it references (here z). References aren't like pointers, which are an actual objects themselves.
In the case of your assignment:
1 2 3 4
int a = 9, b = 0;
if(b = a){ DoStuff; }
//This will return a reference (the actual value of) b back, which in this case will have
//been changed to 9, which being !=0 is true.
Ah ok cool :) I always see these posts, and I know why they have issues with it, but I was wanting a more deep understanding of what exactly was going on when that mistake is made.
Aah I get it. So, whenever this happens, as long as the right side operand is a non zero, the condition will result in a true?
Not quite. In an attempt to oversimplify, you're making it more complicated.
The right side isn't a clear-cut indicator because there are truncation issues.
Example:
1 2 3 4 5 6
uint8_t a = 5;
int b = 0x100; // too large for uint8_t
if( a = b )
{
// not executed, because a == 0
}
If you want "rules", they would be this:
- Assuming the left side is a basic type: As long as it's nonzero after assignment.
- For complex types that can be implicitly cast to a bool: As long as cast to bool returns true after assignment.
- For complex types that can't be implicitly cast to a bool: compiler error.
But that's overly complicated.
Really, it's as simple as this:
1 2 3 4 5 6
//this:
if(a = b)
// is the same as this:
a = b;
if(a)
If you think of it that way, you'll never go wrong.
What actually happens when you replace comparison with assignment
The assignment will replace the comparision.:)
Assignment is an expression. As any expression it has a result. So the result of the assignment expression will be used in if statement if it can be converted to
bool. For example scalar types can be converted to bool. So an expression of a scalar type can be used in if statemennt.