jeudi 27 septembre 2012

Placement new

J'ai enfin trouvé une utilité à placement new aujourd'hui. Pour rappel, il s'agit de construire un objet (en gros, d'appeler son constructeur) dans un emplacement mémoire déjà alloué.

De fait, tout est venu de la propension du vecteur à initialiser tout ce qu'on lui donne. C'est généralement fort pratique, mais parfois, ce n'est pas le comportement attendu. Par exemple, l'implémentation d'une table de hachage en adressage ouvert, où toutes les valeurs sont placées de manière contigüe en mémoire, nécessite l'allocation d'un bloc, puis la construction (et la destruction) de chaque cellule au fur et à mesure du remplissage de la table.

C'est donc exactement l'approche que j'ai prise: faire un

char * mem = new char[size * sizeof(T)])
pour allouer suffisamment de mémoire pour y placer size objets T. La mémoire n'est pas initialisée, il n'y a donc pas de pénalité à payer en termes de performances. Ensuite,
new (mem + index * sizeof(T)) T
pour construire l'objet au moment où j'en ai besoin. À la destruction, il faut manuellement appeler le destructeur:
reinterpret_cast<T *>(mem + index * sizeof(T))->~T();

lundi 3 septembre 2012

Et pourtant c'était là...

Comment faites-vous pour vérifier si un élément appartient à un std::set? Moi, je faisais set.find(e) != set.end(). Eh ben, il y a encore plus simple: set.count(e). Ça a toujours été là, et je ne m'en étais même pas rendu compte...