Skip to main content
GameDev.net gamedev.net
🔒 Locked

Const object arrays and const object array pointer array?

Started by Athos Nov 23, 2010 at 5:31 AM 10 replies 3.4k views
Original Post
Athos
Athos
Hi there this is a bit weird but for the current situation preferred way to store data.

I need to define and save some static data in my headerfile.

Iv got my object
struct MyObject{int x;int y;MyObject(x,y){x = x; y=y;}}

I need 2...X lists of this object type. The lists are static and should not change.
Is the correct format?
const MyObject* const List1[] ={ new MyObject(5,6), new MyObject(5,6), new MyObject(5,6), 0}


And Lastly i need an array with pointers to allt lists i have already created( IF there is a better solution i am happy to try it out )
const MyObject** const ListList[] = {List1,List2,..}


Main problems I encounter depending on how I write is either "ListList is already defined" although I already use #ifndef "DATA_H" #define "DATA_H" and #endif in the datafile. main.cpp and anotherobject.cpp includes data.h file.

The other problem i encounter is
cannot convert from 'MyObject *const [3]' to 'const MyObject **const '

Any suggestions or alternate solutions are welcome. The code is not really performance dependent but reading writing from disk and or database is not preferred.

~Athos
-Truth is out there-
stevenmarky
stevenmarky
MyObject(x,y){x = x; y=y;}

This looks really scary, does this actually work?

Quote:

The lists are static and should not change.
Is the correct format?
const MyObject* const List1[]

I don't think you need MyObject* there, wouldn't MyObject suffice?

Quote:

ListList is already defined

This is because your ListList is defined inside the header, header inclusion guards won't protect against that. This error is caused because the one definition rule is not being obeyed. To fix it, define ListList in a cpp file instead, and in your header:
extern const MyObject** const ListList[];

Take a look at Wikipedia and Stack Overflow (check the answer) for explanations on why this happens, and why inclusion guards don't protect against it.
Quote:

cannot convert from 'MyObject *const [3]' to 'const MyObject **const '

To fix this your second array type would have to be:
const MyObject* const * const ListList[] 


Read in English, this is an array of constant pointers to constant pointers to constant MyObjects...

This isn't very nice. You could use typedefs to make it more readable or you could use a collection class instead of doing pointer magic, or both:
typedef std::vector<MyObject> ObjectArray;typedef std::vector<ObjectArray> ObjectArrayArray;


You could populate these using a variety of methods. You could just use push_back on the vector, or use something like boost::assign to make it easier:
ObjectArray objectArray;objectArray+= MyObject(5,6),MyObject(5,6),MyObject(5,6);


Another solution would be to make a 2D array. This would only work if each of your sublists are the same length.

[Edited by - stevenmarky on November 23, 2010 6:09:02 AM]
Brother Bob
Brother Bob
Quote:
Original post by stevenmarky
MyObject(x,y){x = x; y=y;}

This looks really scary, does this actually work?

No, because x and y are missing types. But ignoring that, yes, it will work in the sense that it is perfectly valid code; it will assign the argument variables to themselves. If the intention is to initialize the member variables, put the initialization in the initialization list (duh).
MyObject(int x, int y) : x(x), y(y) {}

Not that I think this particular piece is relevant to OP's question in general, as that code is probably more to demonstrate intention than asking about an actual syntax problem, but since you brought it up...
stevenmarky
stevenmarky
No I meant work as in initializing the class member variables (duh)
Athos
Athos
Quote:
Original post by stevenmarky
MyObject(x,y){x = x; y=y;}

This looks really scary, does this actually work?

It would probobly work due to compilermagic. But its not really written so in the code. Just ment to show that i actually have an constructor for the struct.
Quote:

Quote:

The lists are static and should not change.
Is the correct format?
const MyObject* const List1[]

I don't think you need MyObject* there, wouldn't MyObject suffice?

Depends on what you want to achieve i guess. My point was being able to walk through the list and find out how many elements there is. But since i know this when i generate the headerfile i would just have an const int List1Num = X;

Quote:
Quote:

ListList is already defined

This is because your ListList is defined inside the header, header inclusion guards won't protect against that. This error is caused because the one definition rule is not being obeyed. To fix it, define ListList in a cpp file instead, and in your header:
extern const MyObject** const ListList[];
Cant define it in a .cpp file due to this headerfile is generated and i need it to contain all data. needed. And this file is then inlcuded in some .cpp files. The strange thing is that if i use the solution below i dont get the error.


Quote:
Quote:

cannot convert from 'MyObject *const [3]' to 'const MyObject **const '

To fix this your second array type would have to be:
const MyObject* const * const ListList[] 


Read in English, this is an array of constant pointers to constant pointers to constant MyObjects...
Worked like charm.
Quote:

This isn't very nice. You could use typedefs to make it more readable or you could use a collection class instead of doing pointer magic, or both:
typedef std::vector<MyObject> ObjectArray;typedef std::vector<ObjectArray> ObjectArrayArray;



You could populate these using a variety of methods. You could just use push_back on the vector, or use something like boost::assign to make it easier:
ObjectArray objectArray;objectArray+= MyObject(5,6),MyObject(5,6),MyObject(5,6);


If this works with data set in the headerfile this is a more preferred solution. But if it needs to be filled runtime. It becomes a bit of a hazzel.

Edit*
Quote:

Another solution would be to make a 2D array. This would only work if each of your sublists are the same length.

Thay are not and part of the cause i started trying out this configuration.

Thank you
Hope we can see other solutions and such around this.
-Athos


-Truth is out there-
alvaro
alvaro
It is very odd that you would need an array of pointers and then have to use new for each object, unless you need polymorphism. An array of objects should work just fine, has simpler syntax, is more cache friendly and avoids one unnecessary level of indirection.
Athos
Athos
Quote:
Original post by alvaro
It is very odd that you would need an array of pointers and then have to use new for each object, unless you need polymorphism. An array of objects should work just fine, has simpler syntax, is more cache friendly and avoids one unnecessary level of indirection.


If you do not know the size of the object array. How would you determine how many objects the array contains? ( Kinda invalid point since its static and i should always know the exact size of the array before hand but just for the sake of argument )


But yea i have already changed the pointer arrays to be objects arrays.

-Athos
-Truth is out there-
johnstanp
johnstanp
Quote:
Original post by Athos
Hi there this is a bit weird but for the current situation preferred way to store data.

I need to define and save some static data in my headerfile.

Iv got my object
struct MyObject{int x;int y;MyObject(x,y){x = x; y=y;}}

I need 2...X lists of this object type. The lists are static and should not change.
Is the correct format?
const MyObject* const List1[] ={ new MyObject(5,6), new MyObject(5,6), new MyObject(5,6), 0}


And Lastly i need an array with pointers to allt lists i have already created( IF there is a better solution i am happy to try it out )
const MyObject** const ListList[] = {List1,List2,..}


Main problems I encounter depending on how I write is either "ListList is already defined" although I already use #ifndef "DATA_H" #define "DATA_H" and #endif in the datafile. main.cpp and anotherobject.cpp includes data.h file.

The other problem i encounter is
cannot convert from 'MyObject *const [3]' to 'const MyObject **const '

Any suggestions or alternate solutions are welcome. The code is not really performance dependent but reading writing from disk and or database is not preferred.

~Athos


Well, if you know the number of arrays, you can do this:
#include <iostream>#include <boost/array.hpp>#include <vector>struct Object{    int x;    int y;    Object(int x, int y)        :x(x),y(y)    {    }};Object objects1[10] ={   Object(1,2),   Object(2,2),   Object(3,1),   Object(4,0),   Object(2,-5),   Object(7,0),   Object(0,1),   Object(18,5),   Object(6,10),   Object(1024,-1)};boost::array<std::vector<Object>,3 > objects2 ={    std::vector<Object>(&objects[0], &objects[3]),    std::vector<Object>(&objects[4], &objects[6]),    std::vector<Object>(&objects[6], &objects[9])};int main(int argc, char** argv){    return 0;}


[Edited by - johnstanp on November 23, 2010 12:58:22 PM]
johnstanp
johnstanp
We use twice the memory needed for storing the objects. It would be better to do that this way:
Object objects1[10] ={   Object(1,2),   Object(2,2),   Object(3,1),   Object(4,0),   Object(2,-5),   Object(7,0),   Object(0,1),   Object(18,5),   Object(6,10),   Object(1024,-1)};int sizes[3] = {4,3,4}; //size of each array of objects


[Edited by - johnstanp on November 23, 2010 1:41:16 PM]
Zahlman
Zahlman
Quote:
Original post by Athos
If you do not know the size of the object array. How would you determine how many objects the array contains? ( Kinda invalid point since its static and i should always know the exact size of the array before hand but just for the sake of argument )


Well, in the case where you don't know, you would use a container that remembers the size for you, such as std::vector. After all, if you don't know the size ahead of time, you probably will want to change the size at some point anyway, right? :)
Zahlman
Zahlman
Quote:
Original post by johnstanp
We use twice the memory needed for storing the objects.


Really?

Approach 1: Actual array of objects for each 'row', array of pointers to rows for the main list.

Cost: 1 object per object, 1 pointer per row.

Approach 2: Single array of all objects, array of ints storing the starting index of each row.

Cost: 1 object per object, 1 int per row.

On typical 32-bit systems, ints are the same size as pointers.
johnstanp
johnstanp
Quote:
Original post by Zahlman
Quote:
Original post by johnstanp
We use twice the memory needed for storing the objects.


Really?

Approach 1: Actual array of objects for each 'row', array of pointers to rows for the main list.

Cost: 1 object per object, 1 pointer per row.

Approach 2: Single array of all objects, array of ints storing the starting index of each row.

Cost: 1 object per object, 1 int per row.

On typical 32-bit systems, ints are the same size as pointers.


I was speaking of my solution:
Object objects1[10] ={   Object(1,2),   Object(2,2),   Object(3,1),   Object(4,0),   Object(2,-5),   Object(7,0),   Object(0,1),   Object(18,5),   Object(6,10),   Object(1024,-1)};boost::array<std::vector<Object>,3 > objects2 ={    std::vector<Object>(&objects[0], &objects[3]),    std::vector<Object>(&objects[4], &objects[6]),    std::vector<Object>(&objects[6], &objects[9])};


The information is stored twice...This is not exactly twice the size of the information, I admit.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.