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

Vic*_*lio 6 c++ optional unique-ptr

我有一个具有动态分配成员的类(仅在使用它时才分配).

想想这样的事情:

class A {};

class B {
    A* aMember;
};
Run Code Online (Sandbox Code Playgroud)

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

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

AnT*_*AnT 15

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>不涉及动态内存分配/释放,但你为此付出的代价可能是"浪费"内存std::optional<A>.使用std::optional了大量实例和/或大的物体可能被证明是非常浪费的,特别是如果该对象花费其大部分生命周期的空状态.

这意味着目的std::optional并非完全针对可选的长期存储.std::optional本地使用的东西:例如,作为可选的本地值,函数的可选参数,可选的返回值.只要你没有大量实例化这样的对象,长期使用也是可以的.

std::unique_ptr<A> 不浪费内存,但你付出的代价是动态内存分配/释放.

当然,所有权语义也是完全不同的.std::optional是可复制的.std::unique_ptr是可移动的,但不可复制.

  • 因此,对于为延迟实例化的成员(即,当包含类存在时无法构造的任何成员)考虑这个问题的人的经验法则是评估该对象可能存活的运行时比例,以及它的大小,如果它是一个可能只是偶尔或短暂存在的大对象,只需继续使用`unique_ptr`。 (2认同)