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(). Не вижу, что быстрее.