C ++ 11 При очистке shared_ptr я должен использовать сброс или установить в nullptr?

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

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

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

50

Решение

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

Две альтернативы абсолютно эквивалентны в том смысле, что вторая форма (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");
66

Другие решения

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

12

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

0

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

-1
По вопросам рекламы [email protected]