   Extremely basic question on C++ pointers
  Hi again, everyone. I just stumbled upon something which should be pretty basic, but for some reason I can't get it to work correctly.What I want to do is:1.- Create a bidimensional array of pointers. More precisely, I want an array of arrays of pointers.2.- Pass one of the sub-arrays to a function, a constructor to be exact.Here's the code I use:class ClassA{public:ClassA (MyObject *objArray[7]){ this->objArray = objArray; } // Compiler errorprivate:MyObject *objArray[7];};void main(){MyObject *bigArray[7][7];ClassA *a = new ClassA (bigArray[0]);}There's obviously something very wrong with this code, because it doesn't even compile. The compiler says "incompatible types in assignment of 'MyObject**' to 'MyObject*[7]'", which I don't understand, since I declare it as 'MyObject*[7]', not as 'MyObject**'.I tried to change all 'MyObject*[7]' to 'MyObject**', and it does compile this way, but I get runtime errors, and I want to rule out my own pointer incompetence before trying to find this error.So, on to the question: why does the above code not compile, and which is the best way to create and manage such an array?Thanks in advance to everyone.[Edited by - Arreis on June 15, 2009 1:23:32 AM]
  Heya!I tried to do this some years back and hit these same problems! ARGH!I think the solution was in the class instead of having *array[7]'s, change those to **array's   ;  Using MyObject** is correct, but your other problems have to do with invalid memory. Since you are using pointers to pointers, you have to allocate memory yourself to store the pointers in your class. Simply storing the address of the variable passed in is dangerous as if that memory was constructed on the stack, it will be invalid in the class.Here's a simple example of how you go about this task if you are going to use this type of design.class MyObject{int x;};class ClassA{public:   // A pointer to a pointer of objects, passing in the count is a mustClassA (MyObject ** objArray_, int count_){//objArray = objArray_; // Should avoid thisobjArrayCount = count_;// If objArray_ is not on the heap, then you will// want to do this instead.// Allocate memory for the class arrayobjArray = new MyObject *[objArrayCount];// Copy objects, can use memset, but for the sake of// showing what is being done...for(int x = 0; x < objArrayCount; ++x)objArray[x] = objArray_[x];}~ClassA(){// Freeing memory on destruction is important!delete [] objArray;}private:MyObject ** objArray;int objArrayCount;};void main(){MyObject * bigArray[7][7] = {0};ClassA * a = new ClassA (bigArray[0], 7);delete a;}However, any pointers that you assign and store in bigArray must also be dynamically allocated using new as trying to store anything on the stack will also result in the same problem of invalid memory if the object loses scope.For example:void main(){MyObject * bigArray[7][7] = {0};// Bad, bad, when the object loses scope you have// a hanging pointer in the array and in the class.MyObject doNotDoThis;bigArray[0][0] = &doNotDoThis;// This solves the problem from before but introduces a new// problem.MyObject * doThis = new MyObject;bigArray[0][1] = doThis;// Uh oh, now bigArray[0][1] has a pointer to an invalid// object. You would need to add in a mechansim to remove// the pointer from bigArray first, and then delete memory!delete doThis;ClassA * a = new ClassA (bigArray[0], 7);delete a;}You can "force" this stuff to work, but there are generally better ways to go about such things in C++. What exactly are you trying to accomplish from a higher level design perspective?   ;  You can't assign arrays to each other in C or C++.  You have to manually assign each element of the arrays to each other.As far as why it says MyObject** and not MyObject*[7], I suggest you read this on using arrays as parameters (there is a section on it at the end).[edit]Gah!  Double ninja'd!   ;  Even if you were double ninja'd at very least you are Mike tacular :P   ;  Well, thanks for the replies, but you're all basically telling me to do exactly what I'm trying to avoid: copy the object ;)I'll try to explain what I'm trying to do. Basically, I have a variable in one class and I want to give to another class access to that variable. Now more specifically: I have a 2D array of images declared and initialised in 'main', containing sets of animations for sprites. Each of the subarrays contains all the images for a certain animation. Now, I also have objects from other classes which need those animations, but I don't want them to store them, just to know where has the 'main' allocated them, so that if more than one object needs the same animation, I don't end up with two copies of it.So, to sum it up: I have an array of subarrays of images in my main, and I want objects from other classes to know where to find those images, but without replicating them. Any good way to do this?   ;Quote:So, to sum it up: I have an array of subarrays of images in my main, and I want objects from other classes to know where to find those images, but without replicating them. Any good way to do this?Allocating memory to store an array of pointers does not copy the objects. You are simply allocating a block of memory to store the pointers to those objects. With the approach I suggested you can have an array of any length, not just a fixed size. That approach is more practical and efficient compared to a fixed size array where you have a limit on how many objects you can store at max.In my example, objArray will always be an allocation of: sizeof(MyObject *) * count_ where as if you were creating new objects, the array would be an allocation of sizeof(MyObject) * count_. If you changed the size of MyObject, it has no impact on the size of a pointer to the object, which s why pointers are so powerful.So, as long as you understand the caveats that I showed at the end of my post about object scope and lifetime, then the approach will work for what you want to do. You don't have to do it that way if you don't want to, but as you mentioned before you had memory problems which the causes are probably from one of the previously mentioned reasons.Here's a correction to the code you first posted that will fixed the problem you are having compiling. This works too but you are programming in limitations to your design:class MyObject{int x;};class ClassA{public:ClassA (MyObject ** objArray_){// Have to copy manually rather than assign.// Once again, simple syntax usedfor(int x = 0; x < 7; ++x)this->objArray[x] = objArray_[x];}private:MyObject *objArray[7];};void main(){MyObject *bigArray[7][7];ClassA *a = new ClassA (bigArray[0]);delete a;}You still have to be on the lookout for invalid pointers regardless. Hope that helps!   ;  I see... so there is no simple way to assign the array, I have to assign the pointers one by one no matter what. Well, a bit more cumbersome than I'd like, but if it works, it works ;)Thanks, Drew_Benton and MikeTacular for pointing this out to me!   ;Quote:Original post by ArreisI see... so there is no simple way to assign the array, I have to assign the pointers one by one no matter what. Well, a bit more cumbersome than I'd like, but if it works, it works ;)You don't have to do it one by one, I only showed the simplest form so you get the idea of what to do. Since it's an array, it is in contiguous memory so you can just do it in one line using a memcpy: memcpy(objArray, objArray_, 7 * sizeof(MyObject *));The thing to be careful of is making sure you don't accidentally copy too many elements (for example if you made the array smaller and didn't update that line), don't hard code the size of a pointer (they are 8 bytes on x64 and 4 bytes on x86), and all of the other rules apply of the data that is being stored.You can only use an assignment operator if both of the pointer declerations are the same:class ClassA{public:ClassA (MyObject ** objArray_){objArray = objArray_;}private:MyObject ** objArray;};However, you must guarantee that the memory being passed to ClassA will always exist up to the destruction of any ClassA object. Otherwise, the object will have pointers to invalid memory location and cause crashes if dereferenced. It's usually preferred to keep your own memory for the container of pointers, but it will work either way as long as your program is controlled.   ;Quote:Original post by Drew_BentonThe thing to be careful of is making sure you don't accidentally copy too many elements (for example if you made the array smaller and didn't update that line)I've had this happen to me way too many times. Arreis my advice if you are going to use a fixed size is use a #define directive so if you need to make changes you only have to edit one line.(Or read up on std::vector :) )