Pointer Scope

Jun 22, 2013 at 2:17pm
I'm having trouble understanding the scope/"life-expectancy" of local data pointed to by a pointer that is then returned.

1
2
3
4
5
6
7
8
9
10
11
12
13
int** GetTable(){
	int table1[]={1,2,3};
	int table2[]={4,5,6};
	int table3[]={7,8,9};
	int* table[]={table1,table2,table3};
	return table;
}
int main(){
	int** table=GetTable();
	cout << *table[2] << endl;
	cout << *table[1] << endl;
        return 0;
}


When I compile this code, the compiler warns me that I am returning the address of a local/temporary variable, and that makes sense to me. However, if this is true (which it is), why is it that the first cout statement prints 7 to the console. As far as I can tell, it shouldn't know that the address held by table[2] contains the integer 7. Or at least, it shouldn't contain the integer 7, rather it should contain some junk value, since, at "return table;", the data should be destroyed.

My next question is, if the first cout statement executes properly, why is it that the second cout statement does not? The first cout statement prints 7, while the second cout statement prints a junk value; something I expected to happen for both, not just the one, cout statement.

Thanks guys, have a good one.
Jun 22, 2013 at 2:31pm
The program has undefined behavior. It prints 7 for the first output statement simply because the stack memory with this element was not yet overwritten by something else. However it seems that for the second output statement the memory of the pointed element was already overwritten.
Jun 22, 2013 at 2:36pm
So you're saying that it is not a given that the first cout statement will print correctly?

Follow up question; Were I to make the tables in the GetTable() function static, would that ensure that any statements, using pointers that hold the addresses of the tables in GetTable(), would execute properly?
Jun 22, 2013 at 2:47pm
The storage for all variables with the static storage duration shall last for the duration of the program. So any pointer that points such a variable will have valid address.
Jun 22, 2013 at 2:47pm
Just wondering why you want to do this: normally one could send pointer arguments to the function, then assign stuff to them in the function, that way they will be available in main() for this example.

HTH :-)
Jun 22, 2013 at 2:55pm
> normally one could send pointer arguments to the function, then assign stuff to them in the function,

Normally, one shouldn't use either pointer arguments or pointer return values for this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <vector>

std::vector< std::vector<int> > make_table()
{ return { {1,2,3}, {4,5,6}, {7,8,9} } ; }

int main()
{
    auto table = make_table() ;
    for( const auto& row : table)
    {
        for( int v : row ) std::cout << v << ' ' ;
        std::cout << '\n' ;
    }
}

http://ideone.com/HuSW5z
Jun 22, 2013 at 3:15pm
I'm not trying to do anything with this example per say , this is just a simplified version of a method of managing and handling user input in as efficient and comprehensive way as possible. The "real code" I'm running looks like...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class cCommand{
public:
          string CMDNAME;
          bool HasChildCmds;
          void* _HandleCmd;
          cCommand* ChildCmdTable;
};
class cCommand_Script{
protected:
          string m_name;
public:
          cCommand_Script(string name){
                    m_name=m_name;
          }
          virtual cCommand* GetCommands();
};

class print_command:public command_script{
public:
          print_command:command_script("print_command"){}
          static cCommand* GetCommands{
                    static cCommand printtable[]={{"hello",false,_HandleHello,NULL}.
                              {"goodbye",false,_HandleGoodbye,NULL}};
                    static cCommand commandtable[]={{"print",true,NULL,printtable}};
                    return commandtable;
          }
};
Jun 22, 2013 at 3:29pm
I'm not sure you fully understand what 'static' implies.

If you are making those variables static just so you can return a pointer to them, that is not wise. Also, a routine cannot be both virtual and static.

Why are you returning pointers in the first place? Why not just return by value like normal?
Jun 22, 2013 at 5:57pm


JLBorges wrote:
> normally one could send pointer arguments to the function, then assign stuff to them in the function,

Normally, one shouldn't use either pointer arguments or pointer return values for this.


Disch wrote:
Why are you returning pointers in the first place? Why not just return by value like normal?


In my statement, I was going with the OP's idea of using pointers, (Maybe unconsciously thinking it was C code). And this is better than having static variables.

On reflection, maybe references or smart pointers would be better. And I am thinking the use of these by the OP would be because of the size of the object, making pass by value inefficient.

So, in general having a references to objects as parameters to a function is an efficient way to handle data - and this is what the OP is after?

This is just a statement from my point of view - I am not trying to argue against you guys, because I know you have vastly more knowledge than me.

@billywilliam

Can I point out that you have public and protected member variables? This isn't a good idea either. Instead, have private variables with a public interface. I know that protected variables are a real easy thing to do, but the arguments against public variables apply to protected as well.

Hope all goes well.

Jun 22, 2013 at 6:29pm
@TheIdeasMan: I actually was asking the OP why he was using pointers. I figured you were just continuing with his example.

TheIdeasMan wrote:
And I am thinking the use of these by the OP would be because of the size of the object, making pass by value inefficient.


With move semantics and/or return value compiler optimizations, it is extremely likely that there will be NO performance hit when returning large objects by value because the compiler will optimize out the copy.



I would favor a solution similar to JLBorges' here. Simple, easy to access, no risk of bad/dangling pointers, etc. KISS.
Last edited on Jun 22, 2013 at 6:30pm
Jun 22, 2013 at 7:36pm
@Disch

I knew you would have a sensible answer - so thanks !
Topic archived. No new replies allowed.