Comment peut-on initialiser la carte statique, où la valeur est std :: unique_ptr code>?
static void f()
{
static std::map<int, std::unique_ptr<MyClass>> = {
{ 0, std::make_unique<MyClass>() }
};
}
3 Réponses :
Le problème est que la construction de puis appelez-le p> voir < Un href = "http://coliru.stacked-crooked.com/a/dbc251e6248d4379" rel = "NOREFERRER"> Vivez sur Coliru P> P> std :: initialiszer-list code >
copie son contenu. ( objets dans std :: initialisizer_list code> sont intrinsèquement
const code> em>).
Pour résoudre votre problème: vous pouvez initialiser la carte à partir d'une fonction distincte ...
Sera-ce une différence si init () code> retournera
std :: map <...> && code> (rvalue)? C'est à dire. retourne une rvalue sera meilleur? UPD: avec rvalue il y aura un segfault
@Vladon, ce n'est pas simplement une persistimation de la performance, c'est aussi un bug. Vous retournerez un rvalue code> référence à un objet détruit. Voir Ce ... Le retour par valeur est extrêmement efficace dans des cas comme celui-ci, car c'est son Cerentiellement (c ++ 17) aller profiter RVO
Une autre façon de faire cela est d'utiliser une lambda. C'est la même chose que d'utiliser une fonction distincte, mais met l'initialisation de la carte plus près de l'action. Dans ce cas, j'ai utilisé une combinaison d'un auto et d'un DeclType pour éviter de nommer le type de carte, mais c'est juste pour le plaisir.
Notez que l'argument passé dans la Lambda est une référence à un objet qui a Pas encore été construit au point de l'appel, nous ne devons donc pas y référoir de quelque manière que ce soit. Il n'est utilisé que pour la déduction de type. P>
#include <memory> #include <map> #include <utility> struct MyClass {}; static auto& f() { static auto mp = [mp = std::map<int, std::unique_ptr<MyClass>>{}]() mutable { mp.emplace(0, std::make_unique<MyClass>()); mp.emplace(1, std::make_unique<MyClass>()); return std::move(mp); }(); return mp; } int main() { auto& m = f(); }
Écriture du code de la crâche sur mesure semble ennuyeuse et gêne de la clarté.
Voici un code d'initialisation générique de conteneur générique raisonnablement efficace. Il stocke vos données dans un make_map code> prend un nombre pair d'éléments, le premier étant clé de la deuxième valeur. P> ceci devrait le réduire à: p> Std :: Array Code> Comme une liste d'initialistes, mais il passe au lieu de le faire
const code>. P>
static std::map<int, std::unique_ptr<MyClass>> bob =
make_map(0, std::make_unique<MyClass>());
@ U.Bulle j'ai corrigé 2 petites fautes de frappe et a ajouté un lien vers un exemple en direct qui compile.
J'ai mal classé et enlevé mon commentaire. Pour des raisons d'histoire, j'ai commenté cela sur cela indiquant une compilation échec de la commande Déballage de la commande dans les détails :: make_map et que cela me donne STD :: paire erreur. Tu as raison ça compile maintenant. J'aimerais être capable de l'utiliser sur mon code aussi, je ne sais pas ce qui l'oblige à échouer dans mon cas ici ici Stackoverflow .Com / Questions / 53806687 , c'est probablement un bogue sur le compilateur VStudio. Merci quand même si une solution très intéressante et cool!
@ U.bulle Compiler dans MSVC ? Je ne sais pas pourquoi cela ne sera pas compilé pour vous.
Vous devez fournir un nom de variable pour une chose.