Why was my memory address correct when I returned an object byVal but not when I returned it byRef

Hi everyone, I'll show you the snippet of code that wasn't working.
1
2
3
4
5
cout << "\tBackwards:";
for (it = l.rbegin(); it != l.rend(); --it)
     cout << ' ' << *it;
cout << endl;
break;


I'm trying to reverse iterate through a linked list. The problem, though is that
my "for" loop never returns false. All the address data and such was scrambled and weird. Putting in 2 nodes, it would loop a 3rd time (which it shouldn't do) and then it would break during run time.

Here's my original code for rbegin()

1
2
3
4
5
template <class T>
ListIterator<T> & List<T>::rbegin()
{
	return ListIterator<T>(backPtr);
}


Suddenly, I was able to fix it by simply changing the return byVal.

1
2
3
4
5
template <class T>
ListIterator<T> List<T>::rbegin()
{
	return ListIterator<T>(backPtr);
}



I'm not sure what difference it makes. I'm returning the address of the object (byRef) rather than a copy(byVal). But the data itself should never be changed. Any explanations greatly appreciated.
Last edited on
Stuff created 'on-the-fly', like variables in functions, are allocated in a special part of memory called 'the stack'. You can imagine it as something like an array of bytes where there is stuff used and stuff not used:

1
2
unsigned char the_stack[5000];
unsigned char* stack_pointer = &the_stack[0];

Every time a function is called, parts of the stack get used and stack_pointer gets moved to point to the free space on the stack.

Things that the stack are used for are:
-- the address of where in the code to return to
-- values for arguments to the function
-- space for variables declared inside the function
-- etc

Keep in mind, this is a very simplistic explanation of what happens, but it is also essentially correct.

So when you call the function List<T>::rbegin() and create that unnamed ListIterator<T>(backPtr) object, it is placed on the stack. (It may not have a name, but it must exist somewhere.)

Now, you take a reference to that object -- which is essentially a pointer to some place currently used on the stack -- and then you return. The object goes out of scope, is destructed, and the stack_pointer is adjusted back to what it was before List<T>::rbegin() was called.

Now you have a pointer or reference to a place on the stack that is considered unused. At any point, some other function, or even a piece of code, may use that piece of the stack for something entirely unrelated.

See the problems? Were you allowed to return a reference to a local object (variable in a function):
-- The referenced object would have already been destructed and left in an unusable state
-- The referenced object could actually be part of one or more other objects.

Returning by value gets you a copy of the function's local object, so that the copy is guaranteed to be perfectly valid.

Hope this helps.
Hi Duoas, that was really helpful. Thanks for the great explanation! I'm also already familiar with stacks which probably helped.
Last edited on
> for (it = l.rbegin(); it != l.rend(); --it)
I understand that this is your custom iterator class, however the expected behaviour for a reverse iterator is to go on the opposite direction than a normal iterator.
So if you want to traverse your list backwards you need to increment your reverse iterator
for (it = l.rbegin(); it != l.rend(); ++it)

Edit: `rbegin()' should return a reverse iterator, not a forward iterator pointing to almost_end


By the way, your compiler likely give you a warning about ``returning a reference to a local variable''
(perhaps you need to enable warnings)
Last edited on
Hi ne555, it does give me warnings about returning a reference to a local variable. I wasn't quite sure how to resolve this issue. Also, I don't understand what it was worried about if my code worked. I would love if you could explain it to me though. Explanation appreciated!
@keane: Standard library code uses rbegin with reverse iterators. Using regular iterators is prone to cause headaches to you or to people who uses your code.
A backwards iterator is a proxy class that automatically swap s increments with decrements. There's an helper class, std::reverse_iterator, that could help you.
Check out http://www.cplusplus.com/reference/vector/vector/rbegin/
Topic archived. No new replies allowed.