简体   繁体   中英

What is the practical scenario/example/use of dynamic memory allocation and vector of pointers in C++?

Could you please suggest practical scenario/example/use of dynamic memory allocation and vector of pointers?

If I google, I am getting many websites explaining the concepts of dynamic memory allocation and but not able to get practical scenarios where we can use dynamic memory allocation in C++?

Thanks.

Dynamic memory allocation: when you need to use arrays but don't know what size will be required and the compiler doesn't support run-time size on the array allocations. std::vector is useful.

Vector of pointers: when you need to sort an array of big objects, you shouldn't swap elements directly because some of them (like arrays) can not evade extra copies of POD elements. Swapping pointers is enough here and is faster to do against copying millions of elements.

std::vector<std::shared_ptr<float>> bigArrays;
... allocate ...
// sort elements(big objects/arrays) on their elements at index
std::sort(bigArrays.begin(),bigArrays.end(),
    []
    (std::shared_ptr<float> e1, std::shared_ptr<float> e2)
    {
            return e1[index]<e2[index];
    }
);

Sometimes you have an array of atomics:

// behold the false-sharing!
std::vector<std::atomic<int>> atomics;
atomics.push_back(std::atomic<int>());

not possible to dynamically build after the initialization. Their copy-constructors are deleted. Instead, use a vector of pointers:

std::vector<std::shared_ptr<std::atomic<int>>> atomicPtrs;
atomicPtrs.push_back(std::make_shared<std::atomic<int>>());

Sometimes the data pointed to belongs to another domain:

std::vector<float *> gpuMatrices(100);
for(int i=0;i<100;i++
   cudaMalloc ( gpuMatrices.data()+i, 1024*1024*sizeof(float) );

so that you can't work with plain vectors anymore. Then storing those (eg cuda) buffer pointers in a vector lets you manage the resources.


Sometimes the vector has to support different derived classes of a base class:

std::vector<Dog,Cat,Horse,Elephant> animals;

it won't work. Need to have this:

std::vector<Iquackable*> animals(100);
animals[0]=(Iquackable*)getDuckPtr();
animals[0]->quack(); // "quack"  
animals[1]=(Iquackable*)getCatPtr();
animals[1]->quack(); // "meow"

Sometimes your matrix is so huge that you need to have each row of it local to its own numa node in a computation:

my_1TB_matrix[0]=getDataPtr(x,0); // numa_alloc_local(..) from another thread
my_1TB_matrix[1]=getDataPtr(x,1); // numa_alloc_local(..) from another thread
...

so that a CPU (of a multi-CPU system) working on its own row will have better timings.


Sometimes all you have is a pointer because they include each other:

std::vector<Node *> sparseOctree(5);
octree[0]=getRootNodePtr();
octree[1]=octree[0]->createChildNode();
octree[2]=octree[0]->createChildNode();
octree[3]=octree[1]->createChildNode();
octree[4]=octree[1]->createChildNode();
..

Sometimes you need to roll your own memory pool to make things faster:

std::vector<Memory *> heap(500);
heap[0] = allocateMemory();
heap[1] = allocateMemory(); freeMemory(heap[1]);
heap[2] = allocateMemory(); 
heap[3] = allocateMemory();
defragmentation(heap);

without touching the data the memory holds.

  1. Static allocation: You know the requested memory size at compile time, so you can define an array like:
int buf[20]; // This is an array of 20 ints
  1. Dynamic allocation: You allocate the storage at runtime. For example the needed array size is an input to your progam:
int *buf = new int[n]; // where n is some runtime known number.
<some code...>
delete[] buf; // In this case you must release the memory when you don't need it anymore

For example an usecase of an array of pointers is polymorphism. You have a class Base, and you have Derived classes (ie Der1, Der2, Der3). You want to store many object from those derived classes in an array. But you can't since the array type tells you what can you store in them. So in this case you can store the pointers to the Der* objects in the array, as if it is a Base* object.

struct Base
{
    virtual ~Base() {};
    virtual void doSomething() = 0;
};

struct Der1 : Base
{
    virtual void doSomething(); // define what Der1 does for this function
};

struct Der2 : Base
{
    virtual void doSomething(); // define what Der2 does for this function
};

struct Der3 : Base
{
    virtual void doSomething(); // define what Der3 does for this function
};

int main()
{
    // You allocate memory for Base* types so this is an array of pointers
    Base* some_array[3]; // It can be also dynamically allocated

    // And now you can store Der* in this array as:
    some_array[0] = new Der1();
    some_array[1] = new Der2();
    some_array[2] = new Der3();
    // There we did dynamic allocation with new!!!
    // Since our objects are not in the some_array array, but somewhere in the memory, 
    //   and we store pointers to them in the array

    // And you can do:
    some_array[0]->doSomething();
    some_array[1]->doSomething();
    some_array[2]->doSomething();

    // Release the DYNAMICALLY!! allocated things
    delete some_array[0];
    delete some_array[1];
    delete some_array[2];
}

But there are many other usecases. This is just one of them...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM