в чем смысл std::unique_ptr::get

Разве std::unique_ptr::get не противоречит цели иметь unique_ptr в первую очередь? Я ожидал, что эта функция изменит свое состояние, чтобы она больше не содержала указателя. Есть ли действительно полезное использование std::unique_ptr::get?


person lezebulon    schedule 29.05.2012    source источник
comment
что, если вы хотите передать указатель на объект в библиотеку, например, любой вызов ОС?   -  person Mooing Duck    schedule 29.05.2012
comment
Вы все равно можете сделать std::addressof(*p). Нет необходимости делать вид, что базового указателя здесь нет.   -  person Luc Danton    schedule 29.05.2012


Ответы (6)


Вы используете его каждый раз, когда вам нужно передать необработанный указатель, скажем, на функцию C:

std::unique_ptr<char[]> buffer( new char[1024] );
// ... fill the buffer
int rc = ::write( fd, buffer.get(), len );
person Nikolai Fetissov    schedule 29.05.2012

std::unique_ptr безопасно обеспечивает уникальную семантику владения. Однако это не исключает необходимости в указателях не принадлежащих. std::shared_ptr имеет аналог, не являющийся владельцем, std::weak_ptr. Необработанные указатели работают как std::unique_ptr, не владеющие аналогом.

person bames53    schedule 29.05.2012
comment
Я думаю, что этот ответ должен быть принятым. - person JFFIGK; 11.12.2018

Правило, которому я обычно следую, таково: если вызываемый объект не возится со временем жизни/владением, не передавайте ему умный указатель; скорее, передайте необработанную ссылку C++ (предпочтительно) или необработанный указатель. Я считаю, что гораздо чище и гибче отделить заботу о владении от использования.

person Nevin    schedule 29.05.2012

Когда у вас связаны руки и вам нужно передать указатель на что-то, p.get() читается лучше, чем &*p.

Существует функция, которая изменяет состояние, так что unique_ptr больше не содержит указатель, и эта функция называется release. Это в основном полезно для передачи владения другим интеллектуальным указателям, которые не обеспечивают прямое построение из unique_ptr. Любое другое использование рискует привести к утечке ресурса.

person R. Martinho Fernandes    schedule 29.05.2012
comment
Есть ли теоретически разница в производительности? Я всегда делал &* - person Carbon; 05.09.2018
comment
@Carbon: &*, вероятно, теоретически быстрее, поскольку у него нет гарантии предсказуемости .get(), но впоследствии он практически более опасен, поскольку это может привести к неопределенному поведению. - person Fake Code Monkey Rashid; 23.09.2020

У Херба Саттера есть хорошее объяснение (около 3:40) https://www.youtube.com/watch?v=JfmTagWcqoE

Основное преимущество состоит в том, что уникальный указатель отслеживает, сколько других ссылок существует на этот указатель. Вы работаете только с уникальным указателем, когда работаете с владением. Когда вы хотите что-то сделать с данными с помощью этого указателя, вы передаете необработанный указатель.

person Mikael    schedule 02.08.2017
comment
Основное преимущество состоит в том, что уникальный указатель отслеживает количество других ссылок на этот указатель. Это верно для shared_ptr, а не для unique_ptr. - person Nebula; 09.07.2020
comment
std::unique_ptr не отслеживает, сколько ссылок есть на указатель. Они уникальны, поэтому ссылка ровно одна. Если вам нужен подсчет ссылок, std::shared_ptr — это то, что вам нужно. - person Kai Petzke; 21.07.2020

Существует очевидная ситуация, когда вам нужно вызвать C API или плохо спроектированный C++ API.

person K-ballo    schedule 29.05.2012
comment
Почему C++ API должен быть плохо разработан, если он вынуждает вас использовать конкретную реализацию интеллектуального указателя? Тем более, если сам API не претендует на владение указателем? - person Nicol Bolas; 29.05.2012
comment
Вместо «плохо спроектированный» читайте также «старый, еще до того, как интеллектуальные указатели были в стандартной библиотеке / люди использовали Boost». - person Matthew Walton; 29.05.2012
comment
@NicolBolas: я обычно передаю константные ссылки или ссылки на функции, если эта ссылка умирает в конце вызова. Это делает вызывающий код немного неуклюжим, как foo(*something), но я думаю, что это лучший дизайн, чем использование там указателей, потому что он лучше защищает от ошибок функционального контракта, не накладывая ограничений на тип указателя. - person Sebastian Mach; 29.05.2012