Archived

This topic is now archived and is closed to further replies.

edwinnie

returning an array of pointers???

Recommended Posts

Hi, i need some help here in C/C++. Suppose if i want to return an array of pointers from a function, what should the prototype be? and the return type? eg: //----------- //in Player.h //----------- class Player { public: <####> GetCrystals(); //what should <####> be? private: Crystal* crystals[4]; } //------------- //in Player.cpp //------------- <####> Player::GetCrystals() //what should <####> be? { ... return crystals; } I would be grateful if anyone heelps. thx! Edwin

Share this post


Link to post
Share on other sites
You have several choices:

One might be to let the caller pass a pointer to the array where you function stores the pointers:

void GetCrystals(Crystal *crystal_array);

Another is to simply return a pointer to your internal struct:

Crystal *GetCrystals(void);

Yet another is to use a vector (best, IMO):

void GetCrystals(std::vector<Crystal *> &crystal_vector);
std::vector<Crystal *> GetCrystals(void);


Share this post


Link to post
Share on other sites
for instance.

if you are returning an int from a function then the prototype would look like this:

int returnInteger ();


so using that same train of thought, if you want to return an array of pointers to Crystal:

Crystal* returnCrystals ();


hope that helps.

Share this post


Link to post
Share on other sites
quote:
Original post by Alpha_ProgDes
so using that same train of thought, if you want to return an array of pointers to Crystal:

Crystal* returnCrystals ();

Not necessarily wrong, but note that you are not returning any Crystal pointers, but only a pointer to an interal array not owned by the caller.

I don't really know if it is possible to return an array , ie. type[8] Function(void); but besides that your only choices are to return an object (std::vector, std::list, or your own kind).

In most cases I would argue using a STL vector, but that might not necessarily be the best solution in your case as I don't know your needs:

std::vector<Crystal *> GetCrystals(void)
{
std::vector<Crystal *> list;
for(int i = 0; i < sizeof(crystals); i++)
list.push_back(crystals[i]);
return list;
}




[edited by - CWizard on May 5, 2003 8:33:30 AM]

Share this post


Link to post
Share on other sites
thx fer all the replies so fast!

looks like i missed out abit of info
suppose,


class Playarea
{
...
void Generate(<####> arrayptr_crystals)
{
}
}


so somewhere in the code, i would want to use the accessor function defined in Player class:

Generate( player->GetCrystals() );

//player is a ptr eg: Player* player;

the accessor function will return an array of pointers for usage in the Generate() function.

thx!

Edwin

Share this post


Link to post
Share on other sites

Crystal* returnCrystals()
{
static Crystal crystals[length];
int item;

//do some kinda code

for (int i = 0; i < length; ++i)
crystals[ i ] = item;

return crystals;
}



if the array is static the function doesn't destroy the array as it's still in memory. i remember making a similar mistake in my C class. just in that class i didn't make the array static, it was just local.
(adjust to reflect an array of pointers, later )

edit: my array made everything italic, lol

[edited by - Alpha_ProgDes on May 5, 2003 8:42:10 AM]

Share this post


Link to post
Share on other sites
Alpha_ProgDes, that is not a good solution. How will the caller know the number of elements in the array? You may know it now, but it is not good practice to rely on hardcoded numbers in that way. A better version of yours is:

std::vector<Crystal *> &Player::GetCrystals(void)
{
static std::vector<Crystal *> list;
list.clear();
for(int i = 0; i < sizeof(crystals); ++i)
list.push_back(crystals[i]);
return list;
}
Then you could keep the original crystal list in a vector as well, and simply return a reference to it.

Otherwise, you could work with these functions:

std::vector<Crystal *> Player::GetCrystals(void);
void Playarea::Generate(const std::vector<Crystal *> &crystal_list);

// and use them like this
play_area.Generate(player1.GetCrystals());


EDIT: minor HTML mistakes

[edited by - CWizard on May 5, 2003 8:58:17 AM]

Share this post


Link to post
Share on other sites
i must say, i am not realli gd at STL yet,
so i kept getting errors like "vector is not a member of ''std''"?

hmm...i might have noticed:

void GetCrystals(std::vector &crystal_vector);
std::vector GetCrystals(void);

or

std::vector Player::GetCrystals(void);


hmm... return type is a std::vector? or std::vector?

and how come function arguments are different? one is void and the other is std::vector &crystal_vector?

heelps!!

Edwin

Share this post


Link to post
Share on other sites
Wait a minute... Aren''t arrays global? IE, couldn''t you do something like this:

  
int main{
Crystal* array[5];
GetCrystal();
return 0;
}

void GetCrystal();
{
for(int i = 0; i < 5; ++i)
{
array[i] = &Something[i];
}
}


Of course, I could be totally wrong.


Curse you windows and your poor explanation of my errors!!!

Share this post


Link to post
Share on other sites
quote:
Original post by edwinnie
i must say, i am not realli gd at STL yet,
so i kept getting errors like "vector is not a member of 'std'"?
You should get yourself familiar with it; it's really handy. You must have an #include <vector>. Some poeple also use using namespace std; so they don't have to qualify the namespace (std::xxx), but I think it is good to be explicit.
quote:
hmm...i might have noticed:

void GetCrystals(std::vector<Crystal *> &crystal_vector);
std::vector<Crystal *> GetCrystals(void);

or

std::vector Player::GetCrystals(void);


hmm... return type is a std::vector? or std::vector<Crystal*>?
I'm not sure what you are asking about here. The first one you could use like this:

std::vector<Crystal *> crystal_list;
player.GetCrystals(crystal_list); // function will "build" your crystal_list
play_area.Generate(crystal_list);


The second return the whole vector object, and could be used like this:
play_area.Generate(player.GetCrystals());

Your alternate approach won't work; you need to specify a type which the vector should hold. In this case Crystal *.
quote:
and how come function arguments are different? one is void and the other is std::vector<Crystal*> &crystal_vector?
Alternate approaches. You can either tell the function where to store the pointers, or let the function return them. The latter is cleaner , but is less efficient. In the former case you only need to pass a reference (a pointer) to the function which don't have to return anything, while the latter needs to return an object that is possibly 4 times the size of a pointer.

[edited by - CWizard on May 5, 2003 9:25:17 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by Chigaimasu
Wait a minute... Aren''t arrays global?
No, not unless you declare them global. There is nothing special about arrays in that regard.

Share this post


Link to post
Share on other sites
quote:
Original post by Chigaimasu
Wait a minute... Aren't arrays global? IE, couldn't you do something like this:

Of course, I could be totally wrong.


Curse you windows and your poor explanation of my errors!!!


You are totally wrong.
Why all the STL discussion? Crystal** should work...

[edited by - novum on May 5, 2003 9:27:23 AM]

Share this post


Link to post
Share on other sites
suppose if i use Crystal** as the return type,
and there is an array of pointers: Crystal* crystals[4];


then if this function has a prototype:
void Generate(Crystal** ptr_To_arrayptrs);

i could call it by using Generate( player->GetCrystals() );

but inside Generate() function,
i need to access "crystal[0], crystal[1], ..."

issit just by stating,
crystal[0]->....
or
&crystal[0]->....
?

thx!

Edwin

Share this post


Link to post
Share on other sites
quote:
Original post by noVum

Why all the STL discussion? Crystal** should work...




He's right, if you don't want to learn STL right now (although I recommend it), Crystal** will work.

Suppose you have a struct Crystal, and classes Player and Play_Area.

crystal has data:
int dummy_value;

Player has data:
int num_crystals;
Crystal* crystals[4]; // Alternatively, Crystal** crystals;

player has functions (assuming you initialize your crystals array):
Crystal** GetCrystals(){ return crystals; }
int GetNumCrystals(){ return num_crystals; }


Play_Area has functions:

void Generate( Crystal** arrayptr_crystals, int num_in_array ){

// Print out the contents of each Crystal
for (int i = 0; i < num_in_array; i++){
printf("Crystals[%d]->dummy_value = %d \n\r",i,arrayptr_crystals->dummy_value);
}}


you can access it by
Generate( player.GetCrystals(), player.GetNumCrystals() )


----
EDIT:

Suppose I'm too slow in the reply.

You access "crystal[0], etc" by

ptr_To_arrayptrs[0]->... (using the above, arrayptr_crystals->dummy_value)


[edited by - KeyS on May 5, 2003 9:40:11 AM]


[edited by - KeyS on May 5, 2003 9:43:32 AM]

Share this post


Link to post
Share on other sites
I would argue against returning an array pointer, because there is no (good) way of telling how many elements it contain.

If you don't want to use STL, you could use a simple struct:

typedef struct {
Chrystal *ptr[4];
} ChrystalList;

// or

typedef struct {
Chrystal **list;
int size;
} ChrystalList;
And throw that or a pointer to it around, as it provides a mean to know how many elements are in the array.

EDIT: Actually, KeyS provided a similar way to solve the unknown-number-of-chrystals problem, and perhaps an easier one.

[edited by - CWizard on May 5, 2003 10:07:53 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by edwinnie
is there a violation?
i seem to get an unhandled exception,

from:

ptr_To_arrayptrs[0]->... (using the above, arrayptr_crystals->dummy_value)

it seems that "ptr_To_arrayptrs" points to an "array of pointers", so isnt this a violation:

ptr_To_arrayptrs[0]->...


//in order to access crystals[0]
should it be ptr_To_arrayptrs->crystals[0]->...


someone pls clarify.
thx!

Edwin




ptr_To_arrayptrs is Crystal**, or an array of pointers

ptr_To_arrayptrs[0] is Crystal*, because [] dereferences 1 level of pointer

ptr_To_arrayptrs[0]->x is entirely dereferenced because -> dereferences the 2nd and final level of pointer

an unhandled exception might be from not having a valid memory address at "dummy_value" (ptr_To_arrayptrs[#]->dummy_value), did you initialize your array of pointers at all?

Assume you have the struct crystal with 1 int dummy in it, and class Player with Crystal* crystals[4] in it, somewhere in the code (constructor is a good place), you''d need

crystals[0] = new Crystal;
crystals[0]->dummy = 0; // initialization value, could be anything
...(repeat for 1-3)...

Alternatively, you could make Crystal a class and have it''s own constructor so you wouldn''t have to type "crystals[0]->dummy = 0;" for every time you type "crystals[0] = new Crystal;"

Is this your problem?

Share this post


Link to post
Share on other sites
First of all think about what an array is. All arrays get resolved down to pointers, its just that arrays are easier for some people. So if you want to return a pointer to an array of pointers, simply return the address of the first element(either in array/pointer notation), and the indirection will take care of everything.

Share this post


Link to post
Share on other sites