83 votes

C++11 Lors de l'effacement d'un shared_ptr, dois-je utiliser reset ou set to nullptr ?

J'ai une question concernant les meilleures pratiques de C++11. Lors de l'effacement d'un shared_ptr, dois-je utiliser la fonction reset() sans paramètre, ou dois-je définir la fonction shared_ptr à nullptr ? Par exemple :

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

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

97voto

Andy Prowl Points 62121

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

Les deux alternatives sont absolument équivalentes, dans le sens où la deuxième forme ( foo = nullptr ) est définie en fonction 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;

8 Effets : reset() .

9 Postcondition : get() == nullptr

10 Retours : *this .

C'est pourquoi, il suffit de choisir celle dont l'intention est la plus claire pour vous . Personnellement, je préfère :

foo = nullptr;

Parce qu'il est plus évident que nous voulons que le pointeur soit nul. En règle générale, cependant, essayez de minimiser les situations où vous devez explicitement réinitialiser un pointeur intelligent.


Par ailleurs, plutôt que d'utiliser new :

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

Envisager d'utiliser std::make_shared() dans la mesure du possible :

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

17voto

Walter Points 7554

Je préférerais reset() car il signale l'intention. Cependant, essayez d'écrire votre code de telle sorte que vous n'ayez pas besoin de explicitement effacer un shared_ptr<> c'est-à-dire garantir que a shared_ptr<> sort du champ d'application alors que vous auriez pu l'effacer.

5voto

r0ng Points 558

Ils sont un peu différents 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, assigne l'objet nouvellement créé à la variable et appelle le destructeur pour détruire la chaîne.

Puisque je ne sais pas comment vérifier ce qui s'est passé dans la fonction reset(). Je ne vois pas ce qui est le plus rapide.

-1voto

Xaltar Points 612

En général, les pointeurs intelligents peuvent se gérer eux-mêmes. Mais si vous avez besoin d'une solution, la fonction reset() est, à mon avis, votre meilleur atout.

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