Подтвердить что ты не робот

С++ 11 При очистке shared_ptr следует использовать reset или установить значение nullptr?

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

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

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

4b9b3361

Ответ 1

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

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

 unique_ptr& operator=(nullptr_t) noexcept;

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

9 Постусловие: get() == nullptr

10 Возвраты: *this.

Поэтому просто выберите тот, который делает его цель более ясным для вас. Лично я предпочитаю:

foo = nullptr;

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


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

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

По возможности используйте std::make_shared():

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

Ответ 2

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

Ответ 3

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

Ответ 4

Они немного отличаются, если вы используете 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(). Невозможно увидеть, что быстрее.