At std::make_unique
- il des avantages d'efficacité comme std::make_shared
?
Par rapport à la construction manuelle std::unique_ptr
:
std::make_unique<int>(1); // vs
std::unique_ptr<int>(new int(1));
At std::make_unique
- il des avantages d'efficacité comme std::make_shared
?
Par rapport à la construction manuelle std::unique_ptr
:
std::make_unique<int>(1); // vs
std::unique_ptr<int>(new int(1));
make_shared
a- t -il une efficacité sur la simple écriture du code à main longue?make_shared
peut allouer à la fois l'espace pour l'objet et l'espace pour le bloc de contrôle en une seule allocation. Le coût est que l'objet ne peut pas être désalloué séparément du bloc de contrôle, donc si vous en utilisezweak_ptr
beaucoup, vous pouvez finir par utiliser plus de mémoire.Réponses:
La motivation derrière
make_unique
est principalement double:make_unique
est sûr pour créer des temporaires, alors qu'avec une utilisation explicite de,new
vous devez vous souvenir de la règle de ne pas utiliser de temporaires sans nom.L'ajout de
make_unique
finalement signifie que nous pouvons dire aux gens de «ne jamais» utilisernew
plutôt que la règle précédente de «ne jamais» utilisernew
sauf lorsque vous faites ununique_ptr
».Il y a aussi une troisième raison:
make_unique
ne nécessite pas d'utilisation de type redondant.unique_ptr<T>(new T())
->make_unique<T>()
Aucune des raisons n'implique l'amélioration de l'efficacité d'exécution comme le fait l'utilisation
make_shared
(en évitant une deuxième allocation, au prix d'une utilisation de mémoire de pointe potentiellement plus élevée).* Il est prévu que C ++ 17 inclura un changement de règle qui signifie que ce n'est plus dangereux. Voir les documents du comité C ++ P0400R0 et P0145R3 .
la source
std::unique_ptr
etstd::shared_ptr
c'est pourquoi nous pouvons dire aux gens de «ne jamais utilisernew
».make_shared
, toutmake_unique
comme le dernier élément qui manquait auparavant.f
:f(unique_ptr<T>(new T), function_that_can_throw());
- de citer la réponse: Le compilateur est autorisé à appeler (dans l' ordre):new T
,function_that_can_throw()
,unique_ptr<T>(...)
. Évidemment, sifunction_that_can_throw
jette réellement, vous fuyez.make_unique
empêche ce cas. Donc, ma question est répondue.std::make_unique
etstd::make_shared
sont là pour deux raisons:std::unique_ptr
ou lesstd::shared_ptr
constructeurs. (Voir la section Notes ici .)Ce n'est pas vraiment une question d'efficacité d'exécution. Il y a un peu le bloc de contrôle et l'
T
attribution en même temps, mais je pense que c'est plus un bonus et moins une motivation pour que ces fonctions existent.la source
std::make_shared
garantira qu'au moins l'un d'entre eux sera enveloppé dans le pointeur intelligent avant que l'autre allocation de mémoire ne se produise, donc aucune fuite.Une raison pour laquelle vous devriez utiliser
std::unique_ptr(new A())
oustd::shared_ptr(new A())
directement à la placestd::make_*()
est de ne pas pouvoir accéder au constructeur de la classe enA
dehors de la portée actuelle.la source
Considérez l'appel de fonction
Supposons que new
A()
réussisse, mais que newB()
lève une exception: vous l'attrapez pour reprendre l'exécution normale de votre programme. Malheureusement, le standard C ++ n'exige pas que l'objet A soit détruit et que sa mémoire soit libérée: la mémoire fuit silencieusement et il n'y a aucun moyen de la nettoyer. En enveloppant A et B,std::make_uniques
vous êtes sûr que la fuite ne se produira pas:Le point ici est que
std::make_unique<A>
etstd::make_unique<B>
sont maintenant des objets temporaires, et le nettoyage des objets temporaires est correctement spécifié dans le standard C ++: leurs destructeurs seront déclenchés et la mémoire libérée. Donc, si vous le pouvez, préférez toujours allouer des objets en utilisantstd::make_unique
etstd::make_shared
.la source