J'avais rapidement et indirectement parlé de std::make_shared ici, et en particulier l'optimisation qui consiste à allouer la structure de contrôle avec l'objet lui même, économisant ainsi une allocation. Prouvons donc que la bibliothèque C++ standard fournie avec g++ le fait effectivement. Prenons un programme qui alloue 100 pointeurs partagés:
#include <memory> #include <vector> int main() { std::vector<std::shared_ptr<int> > v; for(int i = 0; i < 100; ++i) { //v.push_back(std::make_shared<int>(5)); v.push_back(std::shared_ptr<int>(new int(5))); } return 0; }
Faisons tourner la chose avec valgrind. Quand la première ligne à l'intérieur de la boucle est commentée, c'est à dire que l'on alloue un entier, puis qu'on le passe à un pointeur partagé, valgrind nous indique ceci:
==4484== HEAP SUMMARY: ==4484== in use at exit: 72,704 bytes in 1 blocks ==4484== total heap usage: 209 allocs, 208 frees, 79,584 bytes allocated
Le chiffre important, ici, c'est les 209 allocations: 100 allocations d'entiers, 100 allocations de structure de contrôle, et j'aurais envie de dire 8 allocations pour le vecteur et 1 allocation en dehors de notre contrôle. Maintenant, commentons la deuxième ligne et décommentons la première. Valgrind nous dit alors:
==4491== HEAP SUMMARY: ==4491== in use at exit: 72,704 bytes in 1 blocks ==4491== total heap usage: 109 allocs, 108 frees, 79,184 bytes allocated
Yay! Nous avons effectivement une seule allocation dans la boucle au lieu de 2, le make_shared a donc bien alloué la structure de contrôle avec l'objet. À noter que la taille totale allouée est légèrement plus basse, peut-être grâce à des histoires d'alignement?
Aucun commentaire:
Enregistrer un commentaire