I know some solutions how to store multidimensional arrays in the (dynamic) memory.
I'd like to share this knowledge because I noticed that not all of the developers understand what is going on in this field.
Let's look at different ways how to create 2-dimension array of objects of the class A which code is below
class A { public: void * operator new(size_t size) { void *p = malloc(size); cout << "new, size: " << size << "\n"; return p; } void * operator new[](size_t size) { void *p = malloc(size); cout << "new[], size: " << size << "\n"; return p; } A() { cout << "A()\n"; id = ++counter; } ~A() { cout << "~A()\n"; } void call() { cout << "id #" << id << ", " << counter << " times constructor of A was called\n"; } static int counter; int id; }; int A::counter = 0;I added some code for tracing operator new, constructor and destructor calls.
Each time the constructor is called value of class static variable counter is incremented by 1 and its new value is assigned to class member variable id.
- The first method and the simplest.
Simply to allocate 2x2 array of A on the stack.cout << "size of A: " << sizeof(A) << "\n"; A z[2][2]; z[1][1].call(); (z[1]+1)->call(); (*z+3)->call();
This piece of code producessize of A: 4 A() A() A() A() id #4, 4 times constructor of A was called id #4, 4 times constructor of A was called id #4, 4 times constructor of A was called ~A() ~A() ~A() ~A()
4 times constructor was called, 4 times destructor, no calls of operator new. - The second, a bit more complex.
Allocate memory for 2x2 array of A in the heap.cout << "size of A: " << sizeof(A) << "\n"; A (*z)[2] = new A[2][2]; z[1][1].call(); (z[1]+1)->call(); (*z+3)->call(); delete [] z;
The output should besize of A: 4 new[], size: 20 A() A() A() A() id #4, 4 times constructor of A was called id #4, 4 times constructor of A was called id #4, 4 times constructor of A was called ~A() ~A() ~A() ~A()
4 times constructor was called, 4 times destructor, 1 call of operator new[] to allocate memory for all 4 objects. - The next method is used to allocate memory in the heap for one-dimension array of size 2 of pointers to A. Then allocate memory for one-dimension 'sub-arrays'.
cout << "size of A: " << sizeof(A) << "\n"; A **z = new A*[2]; z[0] = new A[2]; z[1] = new A[2]; z[1][1].call(); (z[1]+1)->call(); (*z+3)->call(); delete [] z[0]; delete [] z[1]; delete [] z;
size of A: 4 new[], size: 12 A() A() new[], size: 12 A() A() id #4, 4 times constructor of A was called id #4, 4 times constructor of A was called id #4, 4 times constructor of A was called ~A() ~A() ~A() ~A()
2 times constructor was called after each call to operator new[] to allocate memory for 2 objects, 4 times destructor was called - This method is tricky a little bit. We allocate one-dimension array of size 4. Using pointer arithmetics we can simulate two-dimension array.
cout << "size of A: " << sizeof(A) << "\n"; A *z = new A[2*2]; z[2+1].call(); (z+3)->call(); delete [] z;
size of A: 4 new[], size: 20 A() A() A() A() id #4, 4 times constructor of A was called id #4, 4 times constructor of A was called ~A() ~A() ~A() ~A()
4 times constructor was called, 4 times destructor, 1 call of operator new[] to allocate memory for all 4 objects.
- This one is a combination of storing 2x2 array in the heap and in the stack. At first one-dimension array of pointers to A is put onto the stack and later memory from heap is used to allocate one-dimension 'sub-arrays'.
cout << "size of A: " << sizeof(A) << "\n"; A *z[2]; z[0] = new A[2]; z[1] = new A[2]; z[1][1].call(); (z[1]+1)->call(); (*z+3)->call(); delete [] z[0]; delete [] z[1];
size of A: 4 new[], size: 12 A() A() new[], size: 12 A() A() id #4, 4 times constructor of A was called id #4, 4 times constructor of A was called id #4, 4 times constructor of A was called ~A() ~A() ~A() ~A()
2 times constructor was called after each call to operator new[] to allocate memory for 2 objects, 4 times destructor was called
This is upon you.
No comments:
Post a Comment