C++ unique_ptr et carte
Je suis en train d'utiliser le C++0x unique_ptr
de la classe à l'intérieur d'un map
comme suit:
//compile with `g++ main.cpp -std=gnu++0x`
#include <string.h>
#include <map>
#include <memory>
using namespace std;
struct Foo {
char *str;
Foo(char const *str_): str(strdup(str_)) {}
};
int main(void) {
typedef std::map<int, unique_ptr<Foo>> Bar;
Bar bar;
auto a = bar.insert(Bar::value_type(1, new Foo("one")));
return 0;
}
Cependant GCC me donne l'erreur suivante (raccourcis, je pense que c'est la partie pertinente, merci de les tester sur votre propre compilateur C++):
principal.rpc:19: instancié à partir d'ici /usr/include/c++/4.4/bits/unique_ptr.h:214: erreur: supprimé la fonction ‘std::unique_ptr::unique_ptr(const std::unique_ptr&) [avec _Tp = Foo, _Tp_Deleter = std::default_delete]’ /usr/include/c++/4.4/bits/stl_pair.h:68: erreur: utilisé ici
Je ne suis vraiment pas sûr de ce que j'ai fait de mal, cela fonctionne sur MSVC. J'ai trouvé très similaire questions, qui semblent identiques, mais leurs solutions ne fonctionnent pas pour moi.
matt@stanley:/media/data/src/c++0x-test$ gcc --version gcc-4.4.réel (Ubuntu 4.4.3-4ubuntu5) 4.4.3
- Pas la réponse, mais Foo doit avoir un destructeur qui libère str parce que strdup mallocs de la mémoire et des copies str_ dans cette mémoire.
- C'est C++0x, peu importe quand il est officiellement publié. Comme Stroustrup mettre, pense de x comme une hexadécimal 🙂
- Merci pour cette bonne idée 😀
- Franco: Oui, je sais, ce serait la prochaine à mettre en œuvre, mais je n'ai jamais fait cela loin (c'est simplifié, extrait d'un plus grand problème, je vais avoir).
- Vous devez ajouter un destructeur Foo::~Foo qui libère de la mémoire et de désactiver explicitement toute copie.
Vous devez vous connecter pour publier un commentaire.
Première: Votre classe Foo est vraiment une très mauvaise approximation de std::string. Je prédis beaucoup de fuites de mémoire. (Recherche de la "règle de trois".)
Deuxième: Un pointeur n'est pas implicitement convertible en un unique objet (pour des raisons de sécurité). Mais le templated paire constructeur requiert les arguments implicitement convertibles à la valeur respective des types. GCC semble permettre, mais c'est un bug. Vous devez créer l'unique objet manuellement. Malheureusement, le C++0x projet de manque de la suivante, fonction très utile, le modèle qui facilite la création de temporaire unique_ptr objets. Il est également garanti sans exception:
En outre, nous allons utiliser la nouvelle emplace fonction au lieu de insérer:
emplace transmet à la fois les arguments de la paire correspondante constructeur.
Le problème réel dont vous avez été témoin, c'est que la paire constructeur essayé de copier un unique_ptr, même si un tel objet n'est "mobile". Il semble que GCC C++0x support n'est pas encore assez bon pour gérer correctement cette situation. De ce que je peux dire, mon ligne à partir de ci-dessus devrait fonctionner selon les normes en vigueur du projet de N3126).
Edit: j'ai juste essayé suivants comme une solution de contournement en utilisant GCC 4.5.1 expérimentale de C++0x mode:
C'est également censé travailler, dans la norme à venir, mais GCC rejette ainsi. On dirait que vous avez à attendre pour GCC à l'appui de unique_ptr dans les cartes et multimaps.
Clang 3.6.2
ainsiJe ne crois pas qu'il est possible de l'utiliser correctement
unique_ptr
dans unmap::insert
encore. Voici le bug de GCC pour elle:Bug 44436 - [C++0x] Mettre
insert(&&)
etemplace*
dans le associatif et non-ordonnées conteneursIl ressemble, il peut être fixe pour GCC 4.6, mais il ne sera pas construit à partir de SVN sur la vanille Ubuntu 10.04.1 pour confirmer.
Update0
Ce n'est pas le travail comme de GCC svn r165422 (4.6.0).
unique_ptr<Foo>
).Je viens de bricoler avec les unique_ptr dans gcc 4.6.0. Voici quelques (très laid) le code qui fonctionne correctement:
La sortie est de 42, vide, 12 - donc, apparemment, il fonctionne. Aussi loin que je peux dire, le seul "problème" est que terrible à la recherche d'insérer la commande. 'emplace" n'est pas mis en œuvre dans gcc 4.6.0
value_type
estpair<const int,....
) Mais il y a encore un petit problème.w.r.t. exception de sécurité. En général, dynamique de l'allocation d'un objet et de l'initialisation d'un unique_ptr avec le pointeur doit être suivie d'actions. Mais le C++ ne garantit pas l'ordre dans lequel les sous-expressions sont évaluées. C'est pourquoi j'ai utilisé make_unique comme un appel de fonction. De cette façon, il y a deux extra séquence de points.Essayez d'utiliser
emplace
méthode de la carte.