Public Group

# Fundamental Pointer Problems - C++

This topic is 3814 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm new to C++ so I'm not sure if what I'm doing is the flat out wrong way of doing this or not. I made a header file that contains all of the code that generates a map for my game. Here are the first few lines...
[[MapGen.h]]
void MapGen()
{
int MapSize = 0;
int * P_MapSize = &MapSize;
int MapSize_ResourceVar = 0;
In my main chunk of code for the game, I have this (.cpp file):
#include "MapGen.h"
...
void Population_Start()
{
MapGen ();
int Lands = 0;
int Population = 0;
Lands = &MapSize / 4;
Population = Lands;  //grr... define lands in MapGen().  Need pointers to work :)
int Gold = 100;
int * P_Gold = &Gold;
}
Why is the compiler telling me that &MapSize is undefined? As you can probably guess, it does the same thing for &Gold in other functions etc.

##### Share on other sites
Because the pointers are local variables in the functions you are writing. In example when you call MapGen() it creates all the variables does whatever it does with them, and then when the function is done they are all destroyed.

##### Share on other sites
MapSize is a local variable of the function MapGen(), so it cannot be seen outside of that function (in fact, when the function exits the variable no longer exists and is recreated when the function is called again). Same goes for Gold - it can only be seen inside of Population_Start().

Also, writing:
Lands = &MapSize / 4;

is wrong - you are dividing an address by 4, which doesn't really make sense. I think you meant to leave out the '&'.

One other thing - you should declare and initialize your variables at the same time, so instead of writing:

int a;// Somewhere latera = 5;

you would write:

int a = 5;

This will reduce the chance of the variable being used before it was initialized and will cut down on the code size (which is always nice [smile]). Alongside that, you should declare your variables when you need them and not at the start of a function. Besides also preventing the above, it makes it easier to read the code because the variable appears near the place that it is used.

##### Share on other sites
Thanks for the tips!

Ahh... just checked out the scope of variables at cplusplus.com. I thought that I could treat anything I defined as a pointer as a global variable--big mistake (didn't know they would be deleted when the function ended).

Thanks again.

##### Share on other sites
Remember that space for local variables is allocated on the stack. Once a function exits, the memory where its local variables were stored will probably be overwritten by something else on the next function call.

So you could get a pointer to a local variable, but the memory that the pointer points to won't contain valid data after the function exits and another function is called.

Try the code below to see what I mean:
#include <iostream>using namespace std;/* this function returns a pointer to its local variable */int *set_val(int val){        int i = val;        cout << "i = " << i << endl;        return &i;}int main(void){        int *foo, bar;        foo = set_val(42);        bar = *foo;        cout << "bar = " << bar << endl;        /* previous call to cout wrote over the memory foo points to */        bar = *foo;        cout << "bar = " << bar << endl;        return 0;}

On my system, this prints out:
i = 42bar = 42bar = 134519616

##### Share on other sites
Quote:
 Original post by nibbulerAhh... just checked out the scope of variables at cplusplus.com. I thought that I could treat anything I defined as a pointer as a global variable--big mistake (didn't know they would be deleted when the function ended).

I'm guessing you are probably getting confused with pointers and allocated memory.

void f(){    int *i=new int[200];}

After f() exits, the memory allocated still exists, but the pointer i is deleted, so you have no way of accessing the memory or freeing it.

int *f(){    int *i=new int[200];    return i;}void g(){    int *ptr=f();    // do stuff    delete [] ptr;}

Here you are returning a copy of i before it is destroyed, so you can access the memory.

However, all of the above are typical examples of the potential problems with using pointers directly in C++ and why you should almost always prefer to use standard library containers or smart pointers instead.

std::vector<int> f(){    return std::vector<int>(200);}void g(){    std::vector<int> v=f();    // do stuff}

The above is very hard to break, and is unlikely to have any significant performance penalties. Even the apparent additional copy of the vector when being returned is likely to be optimised away by the compiler.

##### Share on other sites
Quote:
 Original post by nibbulerThanks for the tips!Ahh... just checked out the scope of variables at cplusplus.com. I thought that I could treat anything I defined as a pointer as a global variable--big mistake (didn't know they would be deleted when the function ended).Thanks again.

Careful there. The concept of "deletion" is totally irrelevant here. First off, the 'delete' keyword only applies to things that were dynamically allocated (using 'new'), and then it's the pointed-at thing that actually gets "deleted", not the pointer itself. Second, "lifetime" (how long the data is in memory) is a different concept from "scope" (the region of the code in which a given name is understood as referring to the variable).

##### Share on other sites
Quote:
 Original post by EasilyConfusedThe above is very hard to break, and is unlikely to have any significant performance penalties. Even the apparent additional copy of the vector when being returned is likely to be optimised away by the compiler.

You hope. Unless the function is inlined, I don't see how the compiler can avoid the copy.

Personally for something like that I'd prefer passing a reference or pointer to an existing vector and filling it in the function:

void f(std::vector<int>& v){    v.clear();    v.resize(200);}void g(){    std::vector<int> v;    f(v);    // do stuff}

##### Share on other sites
Quote:
 Original post by JeraxYou hope. Unless the function is inlined, I don't see how the compiler can avoid the copy.

Actually, some compilers can use RVO (return value optimization) or NRVO (named return value optimization) in the absence of inlining to eliminate copies. This will be compiler dependent. For instance, see this article about NRVO in MSVC 2005.

##### Share on other sites
Quote:
 Original post by JeraxPersonally for something like that I'd prefer passing a reference or pointer to an existing vector and filling it in the function:

Therefore creating an empty vector, calling the clear() method, then resizing it, all of which you can again only hope the compiler will optimise away. Given that your function might take an empty vector, or an existing vector with data that needs destructing prior to the resize, the chances of this being optimised out are far lower than the RVOs and NRVOs which are well documented parts of the standard that allow the compiler to alter program flow (i.e. remove a copy constructor).

In the case of

std::vector<int> v=f();

the compiler knows that v is empty prior to being filled with the data returned from f(). Having this information puts the compiler in a far better position to optimise.

And interestingly, in the article SiCrane has referred to, MS state that they implement NRVO by the use of a hidden reference parameter to the function, so the under-the-hood code becomes essentially identicle to your example, but with the additional information available to the compiler that the returned-to object is not an existing object containing data.

[EDIT] Actually, I've just realised that a lot of what I said above is nonsense, since the return result from f() could equally be being assigned to an existing vector.

Sorry.

I guess this optimisation is of less benefit over Jerax's explicit reference passing than I thought.

[Edited by - EasilyConfused on January 2, 2008 2:56:25 PM]

• 33
• 12
• 10
• 9
• 9
• ### Forum Statistics

• Total Topics
631352
• Total Posts
2999487
×