С++ 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;
Есть ли какая-либо реальная разница или есть ли преимущества/недостатки для любого подхода?
Ответы
Ответ 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(). Невозможно увидеть, что быстрее.