C'est une fuite de mémoire. Vous initialisez une instance statique de myclass appelée myclass_instance. Vous initialisez également le "shared_ptr myclass :: ptr". Selon Stroustrup [3], les statiques sont initialisées dans l'ordre où elles sont définies. Par conséquent vous avez la définition statique de myclass_instance, qui initialise le ptr interne sur la construction. Cependant, vous avez alors la définition du static myclass :: ptr, qui appelle le constructeur par défaut pour shared_ptr.
Ceci est un exemple du problème classique d'ordre de la statique. Le compilateur pense que myclass :: ptr n'a pas été initialisé, donc il n'y a pas de destruction du shared_ptr original. Au lieu de cela, il est juste fuite.
Vous aurez besoin d'un pointeur nu de quelque sorte. Si vous utilisez C++ 11, vous pouvez faire la technique Nifty Counter avec une instruction d'assignation ternaire qui se déplace sur elle-même si vous déterminez que l'objet a déjà été initialisé. C'est plutôt dur, mais ça fonctionne.
Voilà comment je le ferais en C++ 11:
#include <crtdbg.h>
#include <memory>
using std;
#define _CRTDBG_MAP_ALLOC
#define NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
// Note that the count could also be a field in an initializer static used in the Nifty Counter
// Technique covered in many texts.
static int count = 0; // This gets implicitly initialized to 0 by the executable load into memory.
static struct myclass {
static shared_ptr<int> ptr;
myclass() {
if (count++ == 0) {
ptr = make_shared<int>(0); //initialization
}
}
} myclass_instance;
shared_ptr<int> myclass::ptr = count == 0 ? make_shared<int>(0) : move(myclass::ptr);
int main() {
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF |
_CRTDBG_CHECK_ALWAYS_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
return 0;
}
Voir les éléments suivants pour plus d'informations:
- Lakos, J, 1996, à grande échelle C++ Logiciel de conception. Section 7.8.1.3, Addison Wesley, Reading, Massachusetts.
- Meyers, S, 2005, en vigueur C++, troisième édition. Rubrique 4: Assurez-vous que les objets sont initialisés avant de les utiliser. Addison Wesley, Reading, Massachusetts.
- Stroustrup, B, 2000, Édition spéciale du langage de programmation C++. Section 10.4.9, Addison Wesley, Reading, Massachusetts.
Pourquoi y at-il un deuxième appel à '_CrtSetDbgFlag()' dans la liste des paramètres? – sharptooth
C'est un moyen de combiner deux déclarations en une seule –
Je ne comprends pas. Pourquoi ne pas "ou" quatre drapeaux mais appeler la fonction insidethe la liste "ou"? – sharptooth