В чем разница между пустым и нулевым std :: shared_ptr в C ++?
Страница cplusplus.com shared_ptr
вызывает различие между пустым std::shared_ptr
и null shared_ptr
. На странице cppreference.com явно не указано различие, но используется как «пустое», так и сравнение с nullptr
в описании поведения std::shared_ptr
.
Есть ли разница между пустым и null shared_ptr
? Есть ли какой-либо прецедент для таких указателей со смешанным поведением? Имеет ли смысл не пустой номер null shared_ptr
? Был бы когда-нибудь случай в обычном использовании (т. Е. Если бы вы явно не построили его), где вы могли бы получить пустой, но не нулевой shared_ptr
?
И любой из этих ответов изменится, если вы используете версию Boost вместо версии C ++ 11?
- Boost async_ * функции и shared_ptr's
- shared_ptr: ужасная скорость
- Разница в make_shared и normal shared_ptr в C ++
- Почему работает std :: shared_ptr
- Как выпустить указатель из boost :: shared_ptr?
- Передача общих указателей в качестве аргументов
- Безопасен ли stream shared_ptr ?
- Как я могу вызвать :: std :: make_shared в classе с только защищенными или частными конструкторами?
- Использование shared_ptr в dll-интерфейсах
- Должен ли я использовать shared_ptr или unique_ptr
- Использование пользовательского удаления с помощью std :: shared_ptr
- Передача shared_ptr как shared_ptr
- Почему нет специализации std :: shared_ptr ?
Это странный угол поведения shared_ptr
. У этого есть конструктор, который позволяет вам сделать shared_ptr
который владеет чем-то, и указывает на что-то еще:
template< class Y > shared_ptr( const shared_ptr& r, T *ptr );
shared_ptr
построенный с использованием этого конструктора, делится владением с r
, но указывает на то, что указывает ptr
(т. ptr
get()
или operator->()
вернет ptr
). Это удобно для случаев, когда ptr
указывает на подобъект (например, элемент данных) объекта, принадлежащего r
.
Связанная с вами страница вызывает shared_ptr
который не имеет ничего пустого , и shared_ptr
который указывает на ничего (т. get() == nullptr
) null . ( Пустой используется в этом смысле по стандарту, null – нет.) Вы можете создать пустой, но не пустой shared_ptr
, но это будет не очень полезно. Пустой, но не нулевой shared_ptr
по сути, является не владеющим указателем, который может использоваться для выполнения некоторых странных вещей, таких как передача указателя на то, что выделено в стеке, функции, ожидающей shared_ptr
(но я бы предложил перфорировать кого бы то ни было сначала поместите shared_ptr
в API).
boost::shared_ptr
также имеет этот конструктор , который они называют конструктором псевдонимов .
Есть ли разница между пустым и null shared_ptr?
Пустой shared_ptr
не имеет контрольного блока, а его счет использования считается равным 0. Копия пустого shared_ptr
– это еще один пустой shared_ptr
. Они оба являются отдельными shared_ptr
s, которые не имеют общего блока управления, потому что у него его нет. Пустой shared_ptr
можно построить с помощью конструктора по умолчанию или с конструктором, который принимает nullptr
.
shared_ptr
null shared_ptr
имеет блок управления, который можно использовать совместно с другими shared_ptr
s. Копия непустого null shared_ptr
является shared_ptr
который имеет тот же блок управления, что и исходный shared_ptr
поэтому счетчик использования не равен 0. Можно сказать, что все копии shared_ptr
имеют один и тот же nullptr
. shared_ptr
null shared_ptr
может быть построен с нулевым указателем типа объекта (не nullptr
)
Вот пример:
#include #include int main() { std::cout << "std::shared_ptr ptr1:" << std::endl; { std::shared_ptr ptr1; std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl; std::shared_ptr ptr2 = ptr1; std::cout << "\tuse count after copying ptr: " << ptr1.use_count() << std::endl; std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl; } std::cout << std::endl; std::cout << "std::shared_ptr ptr1(nullptr):" << std::endl; { std::shared_ptr ptr1(nullptr); std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl; std::shared_ptr ptr2 = ptr1; std::cout << "\tuse count after copying ptr: " << ptr1.use_count() << std::endl; std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl; } std::cout << std::endl; std::cout << "std::shared_ptr ptr1(static_cast(nullptr))" << std::endl; { std::shared_ptr ptr1(static_cast(nullptr)); std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl; std::shared_ptr ptr2 = ptr1; std::cout << "\tuse count after copying ptr: " << ptr1.use_count() << std::endl; std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl; } std::cout << std::endl; return 0; }
Он выводит:
std::shared_ptr ptr1: use count before copying ptr: 0 use count after copying ptr: 0 ptr1 is null std::shared_ptr ptr1(nullptr): use count before copying ptr: 0 use count after copying ptr: 0 ptr1 is null std::shared_ptr ptr1(static_cast(nullptr)) use count before copying ptr: 1 use count after copying ptr: 2 ptr1 is null