web-dev-qa-db-fra.com

Différences entre std :: make_unique et std :: unique_ptr avec new

Est-ce que std::make_unique présente des avantages en termes d’efficacité, comme std::make_shared?

Par rapport à la construction manuelle de std::unique_ptr:

std::make_unique<int>(1);         // vs
std::unique_ptr<int>(new int(1));
111
NFRCR

La motivation derrière make_unique Est principalement double:

  • make_unique Est sans danger pour la création de temporaires, alors qu'avec l'utilisation explicite de new, vous devez vous rappeler la règle selon laquelle vous ne devez pas utiliser de temporaires non nommés.

    foo(make_unique<T>(), make_unique<U>()); // exception safe
    
    foo(unique_ptr<T>(new T()), unique_ptr<U>(new U())); // unsafe*
    
  • L’ajout de make_unique Signifie enfin que nous pouvons dire aux gens de ne jamais utiliser new plutôt que la règle précédente de "jamais" utiliser new sauf lorsque vous faites un unique_ptr ".

Il y a aussi une troisième raison:

  • make_unique Ne nécessite pas l'utilisation d'un type redondant. unique_ptr<T>(new T()) -> make_unique<T>()

Aucune des raisons en cause n'implique une amélioration de l'efficacité d'exécution, contrairement à l'utilisation de make_shared (En raison de la suppression d'une seconde allocation, au prix d'une utilisation potentiellement plus importante de la mémoire).

* C++ 17 devrait inclure un changement de règle qui signifie que ce n'est plus dangereux. Voir documents du comité C++ P0400R et P0145R .

129
bames53

std::make_unique et std::make_shared sont là pour deux raisons:

  1. Vous n'avez donc pas à répertorier explicitement les arguments du type de modèle.
  2. Une exception supplémentaire de sécurité sur l'utilisation de std::unique_ptr ou std::shared_ptr constructeurs. (Voir la section Notes ici .)

Ce n'est pas vraiment une question d'efficacité. Il y a le bit sur le bloc de contrôle et le T étant alloué en une fois, mais je pense que c'est plus un bonus et moins une motivation pour que ces fonctions existent.

11
Timothy Shields

Une raison pour laquelle vous devriez utiliser std::unique_ptr(new A()) ou std::shared_ptr(new A()) directement au lieu de std::make_*() ne peut pas accéder au constructeur de la classe A en dehors de portée actuelle.

6
Volodymyr Lashko