I think you misunderstand what a reference is.
T* -> pointer
&obj -> Address of obj
T& -> reference
int a;
int* b = &a; // &a = Address of a. int* b = b is a pointer to int
int& c = a; // int& c = c is a reference to int.
a& // Not valid syntax
Ah, I think I understand now, but even when I leave out the & after stellarobject the method increments the stellarobject, so in this case, it doesn't make a difference?
Ah now I see, without the & it just returns twice a copy of stellarobject incremented by one, while the other one with the & updates itself twice and gets the 2.
There's just one thing that still bothers me, the id++ basically messes around with the object variable id in both cases, why is it that in the other case it "forgets" the first incrementation?
I mean, it's still acting inside the class.
Why isn't it behaving like this one?Code:stellarobjekt& operator++(){ //Durch das & braucht man keine Temporärvariable, sondern weist die Änderung direkt dem betreffenden Objekt zu. id++; //stellaerobjekt returns a reference to * this itself, while stellarobject without & would just return a copy return(*this); }
Code:void increment(){ id++; }
Last edited by Chris L. Tailor; 09-20-2013 at 03:25 PM.
Let's break that statement down to two lines.
This
stellarobjekt obj;
++(++obj)
can be seen as
So what does this do?Code:stellarobjekt obj; { stellarobjekt tmp = ++obj; ++tmp; }
stellarobjekt tmp = ++obj;
This basically increments the original obj and takes its return value and stores it in a temporary. That temporary is then incremented. But because tmp is a copy of obj, obj is not affected.
Change the class to return a reference and the code becomes
Now tmp is a reference to obj, so obj is incremented instead of a temporary.Code:stellarobjekt obj; { stellarobjekt& tmp = ++obj; ++tmp; }
No, &stellarobject and stellarobject & are not the same.
Don't get hung up on the fact they both use an ampersand. The meanings are completely different. It is context that determines the meaning.
declares a function named foo() that returns a reference to a stellarobjekt, accepts an argument that is a reference to a stellarobjekt (named p). The return statement means that reference returned by the function is the one passed by the caller (p).Code:stellarobjekt &foo(stellarobjekt &p) { return p; }
It gets worse, as & is also the address-of operator
In this case, foo() returns a pointer to a stellarobjekt. The argument is a reference to a stellarobjekt. The return value is the address of the object passed (p).Code:stellarobjekt *foo(stellarobjekt &p) { return &p; }
It is also possible to do
In this case, foo() returns the value of a stellarobjekt (not a reference to a pointer). p, again, is a reference. The "return p;", however, causes the caller to receive a copy of p.Code:stellarobjekt foo(stellarobjekt &p) { return p; }
So to put it all in a nutshell:
In the average case id++ is equal to id = id+1
Inside the operation overload function a++ means something totally different,
correct?Code:stellarobject operator++(){ stellarobject pointer(*this); id++ // is equal to stellarobjekt& tmp.id = ++obj.id; ++tmp.id; return(*this); }
What average case? What do you mean by "equal to"?
If by "equal to" you mean "has same effect as", the answer is "sometimes". Depending on the context where it is done, the behaviours can be different.
The expressions "j = id++" and "j = id = id + 1" give different results for j, but both increment id.
Not really, no.
Given the expression "a++", what typically happens is something like (in pseudocode).
Code:if (a is a basic type that can be incremented) then a is incremented and the result of the expression is the previous value of a. else if (only one declared operator++() function makes sense in that context) that function is called, so its results and side-effect are provided else if (more than one operator++() function can potentially make sense in that context) compiler complains about ambiguity and rejects the code else the compiler complains about an invalid expression and rejects the code endif
Conventionally, it is a good idea to make an operator++() function do something that can be described as "incrementing its operand" (which is *this if the operator++() is a member function, and an argument if not a member function). However, it is quite possible to write an operator++() that decrements. Doing such things is generally considered bad practice.
The general good practice with all operators is "logically behaves like int". So your implementation of an operator++() should notionally increment its operand and return (depending on whether you are incrementing pre or post increment) return either a reference to the operand or its previous value. So typical implementations of operator++() will look like
Similarly for non-member forms.Code:Something &Something::operator++() // preincrement (also known as prefix form) { // do whatever is necessary to increment *this return *this; } Something Something::operator++(int) // post-increment (or postfix form) { Something temp(*this); // do whatever is necessary to increment *this return temp; }
Well, I understand the implementation, I just wonder why this
and, for instance, thisCode:void increment(){ id++; }
which both use id++, behave different.It seems that id++ has a different meaning in the latter.Code:stellarobject operator++(){ stellarobject pointer(*this); id++ return(*this); }
I thought, what Elysia was trying to tell me, went kinda like this:
In the latter function id++ only increments a copy of *this, which it then returns, it isn't influencing the attributes of the object directly like in my example with void increment() .Code:stellarobjekt obj; { stellarobjekt& tmp = ++obj; ++tmp; }
Last edited by Chris L. Tailor; 09-21-2013 at 01:34 AM.
Well, that's a large part of your problem. You think you understand, but the questions you're asking demonstrate quite clearly that you don't.
Because you think you understand, you are misinterpreting the advise you are receiving.
Why? If id is the same thing (say, an int member of stellarobject) then the statement "id++" has the same effect in both cases.
The difference is that you are not understanding the significance of the lines above and below it
Firstly, you have misnamed "pointer". It is actually a second object that is a copy of *this. It is not a pointer to *this, or to anything else.Code:stellarobject operator++() { stellarobject pointer(*this); id++ return(*this); }
All the function is doing is creating a copy of *this, incrementing this->id, and then returning a second copy of *this. The first copy created (which you have misnamed as pointer) is being destroyed as the function returns. Since this->id has been incremented, the copy returned to the caller has the same value of id that (as far as the caller is concerned) is incremented (assuming the copy constructor of your class is not broken through your misunderstanding as well).
Well .... you've clearly misunderstood what Elysia told you.
You need to read this whole thread again. Except you need to admit that YOU DO NOT UNDERSTAND before you read it again, otherwise you will keep misinterpreting the advice given.
Ok, I did not understand it.
The function, which returns a stellarobject& is only really needed when you want that ++(++obj) returns a 2, that's the case which Elysia described, right?
Otherwise (without returng &) it works perfectly fine if you just write ++obj; ++obj; ,which also equals the 2.
I think, I just misinterpreted what Elysia meant with ++(++obj), I thought ++(++obj) is the same as ++obj; ++obj; , but I was wrong.
I provided a good example of why you should do it. It does not represent the only case where it is necessary. Depending on your code and implementation, you may find that your code generates bugs if you don't do it this way, because this is what we expect.
It's not.I think, I just misinterpreted what Elysia meant with ++(++obj), I thought ++(++obj) is the same as ++obj; ++obj; , but I was wrong.
Again, you can see the operators as function calls:
(obj.operator++()).operator++();
What you must understand here is that the result return from the first expression "(obj.operator++())" is used when the next function call is done.
Therefore,
++(++obj)
does not mean
++obj
++obj
But rather,
stellarobjekt temp = ++obj;
++temp;
You can also see it like
f(g());
vs
g();
f();
Clearly they are not the same. The result of g() is fed into f().