web-dev-qa-db-fra.com

C++ 11 Lors de la suppression de shared_ptr, dois-je utiliser reset ou mettre à nullptr?

J'ai une question sur les meilleures pratiques C++ 11. Lorsque j'efface un shared_ptr, dois-je utiliser la fonction reset() sans paramètre ou dois-je définir le shared_ptr sur nullptr? Par exemple:

std::shared_ptr<std::string> foo(new std::string("foo"));
foo.reset();
foo = nullptr;

Y a-t-il une différence réelle, ou y a-t-il des avantages/inconvénients à l'une ou l'autre approche?

50
user1930581

Existe-t-il une réelle différence ou existe-t-il des avantages/inconvénients à l'une ou l'autre approche?

Les deux alternatives sont absolument équivalentes, en ce sens que la seconde forme (foo = nullptr) est définie en termes de la première. Selon le paragraphe 20.7.1.2.3/8-10 de la norme C++ 11:

 unique_ptr& operator=(nullptr_t) noexcept;

8Effets: reset().

9 Postcondition: get() == nullptr

10 Retourne: *this.

Par conséquent, choisissez simplement celui qui vous explique le mieux l'intention . Personnellement, je préfère:

foo = nullptr;

Parce qu'il est plus évident que nous voulons que le pointeur soit null. Cependant, comme conseil général, essayez de minimiser les situations dans lesquelles vous devez explicitement réinitialiser un pointeur intelligent.


De plus, plutôt que d'utiliser new:

std::shared_ptr<std::string> foo(new std::string("foo"));

Pensez à utiliser std::make_shared() lorsque cela est possible:

auto foo = std::make_shared<std::string>("foo");
66
Andy Prowl

Je préférerais reset() car cela signale l'intention. Cependant, essayez d’écrire votre code de sorte que vous n’ayez pas besoin de explicitement effacer un shared_ptr<>, c’est-à-dire vous assurer qu’un shared_ptr<> est hors de portée lorsque vous le supprimeriez autrement.

12
Walter

Ils ont un peu différent si vous utilisez https://godbolt.org/ pour vérifier
.__ en utilisant gcc (7.2)
foo.reset(); Génère un code d'assemblage 

  lea rax, [rbp-32]
  mov rdi, rax
  call std::__shared_ptr<int, (__gnu_cxx::_Lock_policy)2>::reset()

cependant, foo = nullptr; génère

  lea rax, [rbp-16]
  mov esi, 0
  mov rdi, rax
  call std::shared_ptr<int>::shared_ptr(decltype(nullptr))
  lea rdx, [rbp-16]
  lea rax, [rbp-32]
  mov rsi, rdx
  mov rdi, rax
  call std::shared_ptr<int>::operator=(std::shared_ptr<int>&&)
  lea rax, [rbp-16]
  mov rdi, rax
  call std::shared_ptr<int>::~shared_ptr()

Il crée un pointeur partagé avec nullptr, affecte le nouvel objet créé à la variable et appelle le destructeur à la chaîne de destination.

Depuis que je ne sais pas comment vérifier ce qui s'est passé dans la fonction reset (). Vous ne pouvez pas voir ce qui est plus rapide.

0
r0ng