We run loop on an array of some objects to check some abstract requirement.
[source]#include <stdio.h>
#include <list>
class A {
public:
A() {
printf("A:constructor.\n");
}
~A() {
printf("A:destructor.\n");
}
};
int main() {
std::list<A*> objects;
printf("Allocate 10 objects of A\n");
for (int i = 0; i < 10; i++)
objects.push_back(new A());
printf("Time to die\n");
int list_size = objects.size();
for (int i = 0; i < list_size; i++) {
A* deadbeef = *(objects.begin());
objects.erase(objects.begin());
delete deadbeef;
}
printf("Elements in list: %d\n", objects.size());
}
[/source]
Output:
Allocate 10 objects of A
A:constructor.
A:constructor.
A:constructor.
A:constructor.
A:constructor.
A:constructor.
A:constructor.
A:constructor.
A:constructor.
A:constructor.
Time to die
A:destructor.
A:destructor.
A:destructor.
A:destructor.
A:destructor.
A:destructor.
A:destructor.
A:destructor.
A:destructor.
A:destructor.
Elements in list: 0
But this is now clever 'cause memory allocation is kinda slow operation. Much better if we will save memory for such type of object and use it letter.
[source]
#include <stdio.h>
#include <list>
class A {
public:
A() {
printf("A:constructor.\n");
}
~A() {
printf("A:destructor.\n");
}
void Clear() {
}
};
class AAlloc {
std::list<A*> _cache;
public:
A* Alloc() {
if (!_cache.empty()) {
A* deadbeef = _cache.front();
_cache.erase(_cache.begin());
deadbeef->Clear();
return deadbeef;
}
return new A();
}
void Dealloc(A* obj) {
_cache.push_back(obj);
}
~AAlloc() {
std::list<A*>::iterator itr = _cache.begin();
for ( ; itr != _cache.end(); ++itr) {
delete *itr;
}
}
};
int main() {
std::list<A*> objects;
AAlloc allocator;
printf("Allocate 10 objects of A\n");
for (int i = 0; i < 10; i++)
objects.push_back(allocator.Alloc());
printf("Time to die\n");
{
std::list<A*>::iterator itr = objects.begin();
for ( ; itr != objects.end(); ++itr) {
allocator.Dealloc(*itr);
}
objects.clear();
}
printf("One more allocation of 10 objects\n");
for (int i = 0; i < 10; i++)
objects.push_back(allocator.Alloc());
printf("IT\'S A GOOD DAY TO DIE!\n");
{
std::list<A*>::iterator itr = objects.begin();
for ( ; itr != objects.end(); ++itr) {
allocator.Dealloc(*itr);
}
objects.clear();
}
printf("Elements in list: %d\n", objects.size());
}
[/source]
New output:
Allocate 10 objects of A
A:constructor.
A:constructor.
A:constructor.
A:constructor.
A:constructor.
A:constructor.
A:constructor.
A:constructor.
A:constructor.
A:constructor.
Time to die
One more allocation of 10 objects
IT IS A GOOD DAY TO DIE!
Elements in list: 0
A:destructor.
A:destructor.
A:destructor.
A:destructor.
A:destructor.
A:destructor.
A:destructor.
A:destructor.
A:destructor.
A:destructor.
It's maybe looks pretty tricky but the main reason is speed up application.