Похоже, что std::unique_ptr
решает проблему, которая также может быть решена с помощью семантики перемещения, то есть передачи права собственности на ресурс с уникальным ресурсом. Вот некоторые примеры, когда они, кажется, выполняют ту же работу:Передача единоличного владельца: unique_ptr vs move semantics
class SomeResource { /* resourcey stuff */ };
void ProcessResourcePtr(std::unique_ptr<SomeResource> r) { /* do stuff */ }
void ProcessResourceRvalRef(SomeResource&& r) { /* do stuff */ }
class OwnerOfResourcePtr {
private:
std::unique_ptr<SomeResource> r_;
public:
OwnerOfResourcePtr(std::unique_ptr<SomeResource> r) : r_(std::move(r)) { }
};
class OwnerOfResourceRvalRef {
private:
SomeResource r_;
public:
OwnerOfResourceRvalRef(SomeResource&& r) : r_(std::move(r)) { }
};
int main()
{
// transfer ownership to function via unique_ptr
std::unique_ptr<SomeResource> r1(new SomeResource());
ProcessResourcePtr(std::move(r1));
// transfer ownership to function via rvalue ref
SomeResource r2;
ProcessResourceRvalRef(std::move(r2));
// transfer ownership to instance via unique_ptr
std::unique_ptr<SomeResource> r3(new SomeResource());
OwnerOfResourcePtr(std::move(r3));
// transfer ownership to instance via rvalue ref
SomeResource r4;
OwnerOfResourceRvalRef(std::move(r4));
return 0;
}
На мой взгляд, это как решить почти точно такая же проблема, по-разному. Я не на 100% понимаю преимущества одного из способов против другого. Я знаю, что перемещение указателя, вероятно, быстрее, чем перемещение конструкторов/назначений, хотя оба они обычно считаются достаточно эффективными. Я также знаю, что семантика перемещения позволяет хранить ваши данные в стеке (см. R2, r4) вместо того, чтобы требовать выделения/освобождения кучи с помощью new/malloc/etc (см. R1, r3), который я считаю хорошим предмет (есть?).
В целом, когда следует предпочесть unique_ptr
над семантикой перемещения или наоборот? Существуют ли какие-либо варианты использования, которые могут быть решены только одним или другим?
Если экземпляр не является обязательным, вы должны использовать 'std :: experimental :: optional' или' boost :: optional'. Для этого не имеет смысла использовать 'std :: unique_ptr'. Кроме того, я не думаю, что вопрос OP даже имеет смысл. 'std :: unique_ptr' показывает пакет политики собственности, который можно повторно использовать. Похоже, что это сводится к «Когда я должен использовать« std :: unique_ptr »вместо моей собственной политики владения?». – Rapptz
@Rapptz: 'std :: unique_ptr' является частью стандартного C++, который для некоторых людей является отличным преимуществом перед« экспериментальным »или« boost ». Я согласен с тем, что ОП, похоже, ищет оправдание, чтобы избежать «std :: unique_ptr», когда это действительно полезно. –
'std :: experimental :: optional' технически также является частью стандарта. Точно так же, как вещи в TR1 были частью стандарта в то время. Оба clang и gcc поддерживают 'std :: experimental :: optional'. – Rapptz