Accordingly, in C ++, we have a class:

Class MyClass{ public: double *ptr; void Set(); }; MyClass::Set(){ ptr=new double[10000000]; } 

Further in the main code:

  MyClass *A; A=new MyClass[10000]; 

Then you need to change the dimension of the array A while preserving its elements, the question is how to do it as productively as possible!?

    3 answers 3

    Method in the forehead: create a new array, copy the elements of the old array there, destroy the old array.

    The correct way: use STL.

    PS In this class, where dynamic memory allocation takes place, you need to take care of destroying it in the destructor and copying it in the copy constructor and in the assignment operator. Otherwise, it may end very badly (((

    Pps. Here at a leisure something. Enjoy your meal.

     #include <iostream> #include <cstring> using namespace std; enum {SIZE = 10000, SIZE_CL = 5}; class MyClass { private: double* ptr; void array_cpy (MyClass& mc) { if (!flag) { cout << "Copying array" << endl; ptr = new double [SIZE]; memcpy (ptr, mc.ptr, SIZE*sizeof(double)); } else { cout << "Copying ptr" << endl; ptr = mc.ptr; mc.ptr = 0; } } public: static bool flag ; static int count; void set() { cout << "Creating array" << endl; ptr = new double [SIZE]; for (int i = 0; i< SIZE; i++) { ptr[i] = count; } count++; } double get(int index) { return ptr [index]; } MyClass (): ptr(0) {} MyClass (MyClass& mc) { array_cpy(mc); } MyClass& operator= (MyClass& mc) { array_cpy(mc); return *this; } ~MyClass () { if (!flag && ptr) { cout << "Deleting array" << endl; delete[] ptr; } } }; bool MyClass:: flag = false; int MyClass:: count = 0; int main() { MyClass* aa = new MyClass [SIZE_CL]; for (int i = 0; i < SIZE_CL; i++) aa[i].set(); MyClass::flag = true; MyClass* bb = new MyClass [SIZE_CL*2] ; for (int i = 0; i< SIZE_CL; i++) { bb[i] = aa[i]; } MyClass::flag = false; cout << bb[3].get(400) << endl; delete[] bb; } 

    And now with the vector:

     #include <vector> int main() { vector<MyClass*> vec; for (int i = 0; i < SIZE_CL; i++) { vec.push_back (new MyClass); vec[i]->set(); } cout << vec[3]->get(400) << endl; for (int i = SIZE_CL; i < SIZE_CL*2; i++) { vec.push_back (new MyClass); vec[i]->set(); } cout << vec[3]->get(400) << endl; } 

    Compare the findings of the program and analyze them. I think the vector is faster by an order of magnitude, because it works with an array of pointers to objects and this greatly speeds up the work.

    • The question of how to do this as quickly as possible, because the ptr in each instance of MyClass can refer to a very large amount of data! Just copying the pointer will give nothing, because it is logical in the destructor will be called delete [] which will destroy the allocated memory block ... - rejie
    • You can enter a flag variable, when raised in the destructor and in different copy constructors there, the array of doubles will not be destroyed or copied. Well, and make get-set methods to manage it. In short, we raise the flag in the original objects, create a new array, copy, destroy the old one, drop the flag in new instances. The arrays of doubles remained in place and pointers to them were preserved. - skegg
    • They brought me to the idea, and if you do not use flags, and in the class copying method to block the destructor (delete [] ptr) just copy the pointer newptr = ptr, and set the native ptr to NULL, will the destructor be called correctly !? - rejie
    • So after all @mikillskegg wrote: use STL (Stepanov and Lee Library). Instead of the array MyClass use vector. There is also std :: vector <> :: resize - alexlz
    • And what is the use in this case STL guarantees performance !? - rejie

    There is an approach in which a large array is stored as a tree of sub-arrays. There is a base array (let's call it a) it stores pointers to arrays (bi) and is long for each of them. When requesting an element x from a given array, the array "a" is first accessed; it determines in which of the arrays "b" the given element is located and takes it from there. This approach is very convenient when resizing an array. we just need to allocate space for the new array and add a link to it in the array.

    There are still a lot of advantages from the disadvantages of somewhat slower access to the element of the array.

    If you need more details and with pictures write in comments.

      I once competed with the STL, trying to create a container that is faster than the standard one. I wrote a class that writes when its constructor, copy constructor, and destructor is called. When reallocating and removing elements from the middle, vector <MyClass> generated a bunch of messages. In my array, I made it so that the constructor is called only when the element is added, and the destructor when it is deleted. Even with the redistribution of memory elements are not copied and not deleted.

      This is how I achieved it. I allocated memory with the help of malloc and freed through free, which work with empty memory, and not with objects. I caused designers and destructors manually. With the redistribution of memory, I used realloc. No constructors and destructors are called. It turns out that the address of the object has simply changed (and if realloc could simply increase the buffer, it has not changed!). Compared to a vector, this introduces a small limitation: you cannot store objects in a container that rely on the fact that their address will always be the same. In any case, such objects are very rare, and in the vector there are already so many more important restrictions.

      This approach can be applied here:

       struct MyClass { double* ptr; //Ты забыл конструктор и деструктор MyClass() {Set();} ~MyClass() {Clear();} void Set() {ptr=new double[10000000];} void Clear() {delete[] ptr; ptr=nullptr;} }; 

      In the main code:

       MyClass* A=malloc(10000*sizeof(MyClass)); //Вызываем конструкторы for(int i=0; i<10000; i++) new(A+i) MyClass; //... //Работаем с ним до того, как перестанет хватать места //... A=realloc(A, 20000*sizeof(MyClass)); //Вызываем конструкторы для новых 10000 объектов for(int i=10000; i<20000; i++) new(A+i) MyClass; //... //Удаляем for(int i=0; i<20000; i++) a[i].~MyClass(); free(A); 

      Here is used placing new. If there is a compilation error, you may need to include the file new.h. MyClass simply plays the role of some kind of load, no matter what it does and how it allocates memory.

      • one
        Who would have explained to me, because of what the booze? The size of this same A 32bit computer is originally 40kb. Given that its elements refer to 10,000 * 80 million. bytes = 800 billion bytes. And you need to optimize this case (40-80kb). What for? Compared to the total costs, these are such trifles ... Well, okay, this will not work on a 32bit system - there will not be enough addresses. Well, 80-160kb ... - alexlz
      • I took myClass from the question and edited it a little, just adding a constructor and a destructor there. About "10,000 * 80 million bytes = 800 billion bytes" ask the author of the question. > And you need to optimize this business (40-80kb). What for? Compared to the total costs, these are such trifles ... I reduce the number of calls to the constructor and destructor MyClass, and not optimize 40-80 kb. Thanks to this, MyClass.ptr does not need to be copied many times during the redistribution. - gammaker
      • Without @rejie this great wisdom still does not understand. Some kind of spherical horse in a vacuum. - alexlz
      • Spherical horse in a vacuum? Is it something incomprehensible? - skegg
      • If you lean towards STL and there is a need to wrap the whole thing in a DLL, which should return the result, then how to implement it!? How to return a vector !? - rejie 3:38 pm