看起来std::unique_ptr
解决了一个也可以通过move语义解决的问题,即转移唯一拥有资源的所有权。以下是一些例子,它们似乎执行相同的工作:
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;
}
依我之见,这两种方法基本上是以稍微不同的方式解决几乎相同的问题。我并不完全清楚一种方式与另一种方式的优势。我知道指针移动可能比移动构造函数/赋值更快,尽管两者通常被认为非常高效。我也知道移动语义允许您将数据保留在堆栈上(参见r2、r4),而不需要使用new/malloc等进行堆分配/释放(参见r1、r3),我认为这是一件好事(是吗?)。
总体上,在什么情况下应该优先选择unique_ptr而不是移动语义,反之亦然?是否有任何用例只能通过其中一种方法来解决?
std::experimental::optional
或boost::optional
。使用std::unique_ptr
没有意义。此外,我认为OP的问题甚至没有意义。std::unique_ptr
显示了一个您可以重用的所有权策略包。感觉就像是“何时应该使用std::unique_ptr
而不是我的所有权策略?” - Rapptzstd::unique_ptr
是标准C++的一部分,对于某些人来说,这是与“experimental”或“boost”相比的一个明显优势。我同意OP似乎在寻找避免使用std::unique_ptr
的借口,而实际上它非常有用。 - John Zwinckstd::experimental::optional
在技术上也是标准的一部分。就像 TR1 中的东西在当时也是标准的一部分一样。Clang 和 GCC 都支持std::experimental::optional
。 - Rapptzunique_ptr
(如果不明显,我对 c++ 还很新)。我知道unique_ptr
一定有一些优势,否则他们就不会费心去制作它,但由于我的策略还没有引起任何问题,所以我没有看到这些优势。@John Zwinck 很好地描述了我的策略将来会遇到的痛点。@Rapptz,我会阅读各种optional
包的相关内容。无论你是否使用它们,了解它们似乎都是一个好主意。谢谢大家。 - Brian Putnamstd::experimental
不是任何标准的一部分。TR1
从未成为任何标准的一部分。它们只是实验。您可以将它们视为标准委员会表示:我们对此API感兴趣,并且正在寻求更多的现场经验和反馈。确实,这就是为什么我强烈游说使用命名空间“experimental”,而不是容易被误解的“tr1”的原因。 - Howard Hinnant