191 votes

Avantages de l'utilisation de std :: make_unique par rapport au nouvel opérateur

Quels sont les avantages de l'utilisation de std::make_unique sur le new de l'opérateur pour l'initialisation de l' std::unique_ptr?

En d'autres termes, pourquoi

std::unique_ptr<SomeObject> a = std::make_unique(SomeObject(...))

mieux que de le faire

std::unique_ptr<SomeObject> a = new SomeObject(...)

J'ai essayé de regarder beaucoup en ligne et je sais que c'est une bonne règle de base pour éviter à l'opérateur new en C++ moderne, mais je ne sais pas quels sont les avantages de ce scénario exact. N'empêche tout type de fuites de mémoire qui pourrait arriver? Est-il plus rapide de faire un std::make_unique utilisation new?

199voto

40two Points 8224

Avantages

  • make_unique enseigne à des utilisateurs "ne jamais dire new/deleteet new[]/delete[]" sans avertissements.

  • make_unique d'actions deux avantages avec make_shared (à l'exclusion de la troisième avantage, l'augmentation de l'efficacité). Tout d'abord, unique_ptr<LongTypeName> up(new LongTypeName(args)) doit mentionner LongTypeName deux fois, alors que auto up = make_unique<LongTypeName>(args) mentionne qu'une seule fois.

  • make_unique empêche la non spécifié-évaluation-commande fuite déclenchée par des expressions comme foo(unique_ptr<X>(new X), unique_ptr<Y>(new Y)). (Suivant les conseils de "ne jamais dire new" est plus simple que "ne jamais dire new, à moins que vous donnez immédiatement à un nommé unique_ptr".)

  • make_unique est soigneusement mis en œuvre pour l'exception de sécurité et est recommandé en appelant directement unique_ptr constructeurs.

Quand ne pas utiliser make_unique

  • Ne pas utiliser make_unique si vous avez besoin d'un custom deleter ou l'adoption d'un pointeur brut d'ailleurs.

Sources

  1. Proposition d' std::make_unique.
  2. Herb Sutter est GotW #89 Solution: des Pointeurs Intelligents

96voto

WhiZTiM Points 3351

La différence est que, std::make_unique renvoie un objet de type std::unique_ptr et new renvoie un pointeur sur l'objet créé. Pour les échecs d'allocation de mémoire, ils seront à la fois de lancer. Tenez-vous bien, il n'est pas simple. Lire plus loin.

Considère la fonction ci-dessous:

void func(ClassA* a, ClassB* b){
     ......
}

Lorsque vous effectuez un appel, comme func(new A(), new B()); Le compilateur peut choisir d'évaluer les arguments de la fonction, de gauche à droite, ou dans n'importe quel ordre il le souhaite. Supposons gauche à droite de l'évaluation: Ce qui se passe lors de la première new expression réussit, mais le deuxième new expression jette?

Le réel danger est lorsque vous prenez une de ces exceptions; Oui, vous avez peut-être pris l'exception levée par new B(), et de reprendre le cours normal de l'exécution, mais new A() déjà réussi, et sa mémoire sera silencieusement fuite. Personne pour le nettoyer... * sanglots...

Mais avec make_unique, vous ne pouvez pas avoir une fuite parce que, le déroulement de pile qui va se passer ( et le destructeur de l'objet créé précédemment sera exécuté). Par conséquent, avoir une préférence pour l' make_unique provoquera vous à l'égard de l'exception de sécurité. Dans ce cas, std::make_unique fournit une "Base de l'Exception de Sécurité" que la mémoire allouée et l'objet créé par l' new ne sera jamais orphelins n'importe quoi. Même jusqu'aux extrémités de temps... :-)

Vous devriez lire Herb Sutter GoTW102

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X