C++11 Al borrar ptr compartido, ¿debo usar reset o establecer en nullptr?


Tengo una pregunta sobre las mejores prácticas de C++11. Al borrar un shared_ptr, ¿debo usar la función reset() sin parámetro, o debo establecer el shared_ptr a nullptr? Por ejemplo:

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

¿Hay alguna diferencia real, o hay ventajas/desventajas en cualquiera de los enfoques?

Author: Fantastic Mr Fox, 2013-04-22

4 answers

¿Hay alguna diferencia real, o hay ventajas/desventajas en cualquiera de los enfoques?

Las dos alternativas son absolutamente equivalentes, en el sentido de que la segunda forma (foo = nullptr) se define en términos de la primera. Según el párrafo 20.7.1.2.3 / 8-10 del estándar C++11:

 unique_ptr& operator=(nullptr_t) noexcept;

8 Efectos: reset().

9 Postcondición: get() == nullptr

10 Devoluciones: *this.

Por lo tanto, simplemente elige el que hace que su intención sea más clara para ti. Personalmente, prefiero:

foo = nullptr;

Porque hace más evidente que queremos que el puntero sea nulo. Como consejo general, sin embargo, intente minimizar las situaciones en las que necesite explícitamente restablecer un puntero inteligente.


Además, en lugar de usar new:

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

Considere usar std::make_shared() cuando sea posible:

auto foo = std::make_shared<std::string>("foo");
 61
Author: Andy Prowl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-08 17:25:24

Preferiría reset() ya que indica la intención. Sin embargo, intente escribir su código de tal manera que no necesite explícitamente borrar un shared_ptr<>, es decir, asegúrese de que un shared_prt<> salga del alcance cuando de otra manera lo borraría.

 12
Author: Walter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-01 13:55:14

Generalmente, los punteros inteligentes pueden manejarse solos. Pero si necesita una solución, el reset() es, en mi opinión, su mejor opción.

 0
Author: Xaltar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-22 16:07:06

Tienen un poco diferente si usas https://godbolt.org / para comprobar
usando gcc(7.2)
foo.reset(); genera código de ensamblado

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

Sin embargo, foo = nullptr; genera

  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()

Crea un puntero compartido con nullptr, asigna el objeto recién creado a la variable y llama a destructor a destory string.

Ya que no se como comprobar lo que paso en la función reset(). No se puede ver que es más rápido.

 0
Author: r0ng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-05 03:29:24