C++11 при очистке общего ptr следует ли использовать сброс или установить значение nullptr?

у меня есть вопрос о c++11 лучшие практики. При очистке shared_ptr я должен использовать reset() функция без параметра, или я должен установить shared_ptr to nullptr? Например:

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

есть ли реальная разница, или есть преимущества/недостатки каждого подхода?

4 ответов


есть ли реальная разница, или есть преимущества/недостатки каждого подхода?

эти два варианта абсолютно эквивалентны, в том смысле, что вторая форма (foo = nullptr) определяется в терминах первого. В пункте 20.7.1.2.3/8-10 из стандарта C++11:

 unique_ptr& operator=(nullptr_t) noexcept;

8 эффекты: reset().

9 постусловия: get() == nullptr

10 возвращает: *this.

таким образом, просто выберите тот, который делает свое намерение ясным для вас. Лично я предпочитаю:

foo = nullptr;

потому что это делает более очевидным, что мы хотим, чтобы указатель был нулевым. В качестве общего совета, однако, постарайтесь свести к минимуму ситуации, когда вам нужно явно сброс смарт-указатель.


кроме того, вместо использования new:

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

рассмотрите возможность использования std::make_shared() когда можно:

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

Я бы предпочел reset() как он сигнализирует о намерении. Однако попробуйте написать свой код так, чтобы вам не нужно было явно очистить shared_ptr<>, т. е. убедитесь, что a shared_prt<> выходит за рамки, когда вы в противном случае очистите его.


как правило, умные указатели могут справиться сами. Но если вам нужно решение, то reset(), на мой взгляд, ваш лучший выбор.


они немного отличаются, если вы используете https://godbolt.org/ проверить
используя gcc (7.2)
foo.reset(); генерирует ассемблерный код

  lea rax, [rbp-32]
  mov rdi, rax
  call std::__shared_ptr<int, (__gnu_cxx::_Lock_policy)2>::reset()
, foo = nullptr; генерирует
  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()

он создает общий указатель с nullptr, назначает вновь созданный объект переменной и вызывает деструктор для строки destory.

так как я не знаю, как проверить, что произошло в функции reset(). Не вижу, что быстрее.