Reputation: 688
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.
Upvotes: 1
Views: 721
Reputation: 11916
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 (e.g. 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.
Upvotes: 1
Reputation: 668
int buf[20]; // This is an array of 20 ints
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...
Upvotes: 1