У меня есть вопрос о лучших практиках C ++ 11. При очистке shared_ptr я должен использовать reset()
функция без параметра, или я должен установить shared_ptr
в nullptr
? Например:
std::shared_ptr<std::string> foo(new std::string("foo"));
foo.reset();
foo = nullptr;
Есть ли какая-то реальная разница или есть преимущества / недостатки любого из этих подходов?
Есть ли какая-то реальная разница или есть преимущества / недостатки любого из этих подходов?
Две альтернативы абсолютно эквивалентны в том смысле, что вторая форма (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<>
обеспечить то, что shared_ptr<>
выходит из области видимости, когда вы иначе очистите его.
Они немного отличаются, если вы используете 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 (). Не вижу, что быстрее.
Как правило, умные указатели могут справиться сами. Но если вам нужно решение, reset()
это, на мой взгляд, ваш лучший выбор.