使用什么 std::optional 或 std::unique_ptr

What to use std::optional or std::unique_ptr

我有一个 class 有一个成员是动态分配的(它只在使用时分配)。

这样想:

class A {};

class B {
    A* aMember;
};

用什么替换 A* 会更好:std::optionalstd::unique_ptr

以及何时使用 std::optional 而不是 std::unique_ptr

std::optional<A> 保证不会发生辅助内存分配。这意味着 A 类型的潜在对象的原始缓冲区嵌入到 std::optional<A> 中。它是 std::optional 内存占用的一个组成部分。这意味着 std::optional<A> 的内存大小将 始终 至少为 sizeof(A),无论该可选 A 对象当前是否存在。那就是 std::optional<A>B.

总大小的贡献

std::unique_ptr<A> 是一个指针。它的大小与普通裸指针的大小大致相同。那就是std::unique_ptr<A>本身在B里面占用的内存量。为了让它指向一个有效的 A 对象,你必须在别处独立地分配那个 A 。当A存在时,占用内存。当A不存在时不占用内存

以上是您做出决定时需要考虑的因素。 std::optional<A> 不涉及动态内存 allocation/deallocation,但您为此付出的代价可能是 std::optional<A> 中的 "wasted" 内存。对大量实例化的 and/or 大型对象使用 std::optional 可能会被证明是非常浪费的,尤其是当对象的大部分生命周期都处于空状态时。

这意味着std::optional的目的并不完全是针对可选的长期存储。 std::optional 是要在 本地 使用的东西:例如作为可选的本地值,函数的可选参数,可选的 return 值。长期使用也是可以的,只要你不是大量实例化这类对象即可。

std::unique_ptr<A>不会浪费内存,但你为此付出的代价是动态内存allocation/deallocation.

当然,所有权语义也大不相同。 std::optional 可复制。 std::unique_ptr可移动,但不可复制。