Help with C++ Pointers, References et al

Started by
7 comments, last by WazzatMan 15 years, 4 months ago
A little background: I know C#, I know Java Never touched a language older than VB in my life I started learning C++ off 'Beginning C++ Game Programming' about a week ago and I just finished the chapter on 'Advanced Classes and Memory Allocation'. I get most of it, it's just different syntax for things that have already been hard-coded into my brain. I don't even think the bugaboo of memory allocation is all that complicated. However, a few questions do come to mind: Memory allocation is neat and all, but why would I use it?. I've heard the stack is actually faster than the heap. Sure I guess you can use it to free memory before going out of scope but at this level I'm finding it pretty hard to picture such a scenario. I'm guessing it would be pretty rare and even avoidable using conventional means. I mean, if you want to limit the lifespan of an object, just encapsulate it in a function, or a subscope, then the stack takes care of it, right?. The author mentions something about data on the heap being interchangeable between functions, but I can do that by returning a regular pointer or even a reference, or would that create a memory leak?. Speaking of references and pointers, is there a performance advantage to be gained by using one instead of the other?. Also, if I create an object on the heap and none of it's members are pointers, does that mean that those members will be created on the heap or the stack?. If any of this is unclear and you want me to post code examples please ask.
Advertisement
Quote:Original post by WazzatMan
I've heard the stack is actually faster than the heap. Sure I guess you can use it to free memory before going out of scope

The point of allocating objects from the heap is for them to outlive the function.

Quote:Original post by WazzatMan
I can do that by returning a regular pointer or even a reference, or would that create a memory leak?

You are not allowed to return the address of a local variable, because once the function returns, that local variable doesn't exist anymore. Every decent compiler will warn you about this.

Quote:Original post by WazzatMan
Also, if I create an object on the heap and none of it's members are pointers, does that mean that those members will be created on the heap or the stack?

If you create an object on the heap, you create an object on the heap.
Quote:The author mentions something about data on the heap being interchangeable between functions, but I can do that by returning a regular pointer or even a reference, or would that create a memory leak?.

You mean like this?

int* return_value (){   int ret = 5;   return &ret;}void other_func (){   int* my_int = return_value ();   // What variable does my_int point to now?}


Returning the address or reference to a stack allocated object is probably not what you want, since the data the pointer/reference is pointing to is no longer valid.

Placing an object on the stack is useful if:
1. The object lifetime is fixed within a function, and the object can fit on the stack.
AND
2. The object can fit on the stack. The stack may be only about 1MB (Platform specific). The "free store" (heap) is usually much larger.

Use the stack if you can, otherwise use the free store.

Quote:if I create an object on the heap and none of it's members are pointers, does that mean that those members will be created on the heap or the stack?

If you create an object on the heap, all of it will be allocated on the heap. That includes the data members. Likewise for the stack.

That's not to say that some of it's members can't be pointing to either a heap or stack object...

Quote:...references and pointers, is there a performance advantage to be gained by using one instead of the other?

If there is, I wouldn't say it's much. Usually that's not the determining factor when deciding which one to use.
Quote:
Quote:Original post by WazzatMan
I can do that by returning a regular pointer or even a reference, or would that create a memory leak?

You are not allowed to return the address of a local variable, because once the function returns, that local variable doesn't exist anymore. Every decent compiler will warn you about this.


Therefore, in theory, the following code shouldn't work:

#include <iostream>using namespace std;int* testWithoutHeap();int main(){ 	int *pTest = testWithoutHeap(); 	*pTest += 20; 	 	cout << *pTest << endl;	  	 	cin.ignore(); 	 	return 0;}int* testWithoutHeap(){ 	 int test = 30; 	 return &test}


Problem is that it does. I get a warning sure, but the screen still outputs 50, meaning the data still exists on the stack and I have a valid pointer to it, which means it wasn't actually removed once I exited from the function.

Quote:Original post by WazzatMan
Problem is that it does. I get a warning sure, but the screen still outputs 50, meaning the data still exists on the stack and I have a valid pointer to it, which means it wasn't actually removed once I exited from the function.


Welcome to C++, home of undefined behaviour. Enjoy your stay [smile]

For example, lets say you make a minor change:
#include <iostream>using namespace std;int* testWithoutHeap();int ohthenoes() { int x = 42; return x; }int main(){ 	int *pTest = testWithoutHeap();	ohthenoes(); 	*pTest += 20; 	 	cout << *pTest << endl;	  	 	cin.ignore(); 	 	return 0;}int* testWithoutHeap(){ 	 int test = 30; 	 return &test;}

On my system in prints 62. But C++ doesn't mandate what should happen.
Quote:Original post by WazzatMan
Problem is that it does.

No, it doesn't. Returning pointers to local variables from a function yields undefined behavior, which includes "seems to work" for some use cases. Try to call another function before the cout, and you will get garbage.
that is undefined behavior. The thing about undefined behavior is that it sometimes appears to work. In that example, sure, that might work there, since you're not doing anything to the stack in the meantime.

Try doing a few function calls between the point where you get the pointer and when you print it out.

[size=1]Visit my website, rawrrawr.com

Quote:Original post by WazzatMan
Problem is that it does. I get a warning sure, but the screen still outputs 50, meaning the data still exists on the stack and I have a valid pointer to it, which means it wasn't actually removed once I exited from the function.

A believe that this will result in undefined behavior, which means that the compiler is free to do whatever it wants. It might work for now, but the whole point of undefined behaviour is that it's undefined. The next time you do the same thing the program might crash, or your computer might catch fire. Anything can happen really. So while it might sometimes work, there is no guarantee that it will always work. Or in other words, don't do it!

Also, heed the compilers warnings. A warning means that there is a possible bug in your program. You should always fix your code so that you don't get any warnings. If possible, turn on the option in the compiler so that it treats warnings as errors, ie. it stops compiling. That way you will be forced to fix the warnings.
I get it, once a new integer was added to the stack, replacing the old integer which was marked for deletion (Or whatever), the pointer, which was pointing to the first address (Or whatever it was), now switched to it.

Either way, non-conventional code = undefined behavior = possible catastrophe, got it.

Thanks for clearing that up.

This topic is closed to new replies.

Advertisement