我有一个动态分配成员的类(仅在使用时才分配)。
想想这样的事情:
class A {};
class B {
A* aMember;
};
最好替换A*
:std::optional
或std::unique_ptr
?
以及何时使用std::optional
代替std::unique_ptr
答案 0 :(得分:11)
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
占用的内存量。{1}}。为了使其指向有效的A
对象,您必须独立地在其他地方分配A
。当A
存在时,它会占用内存。当A
不存在时,它不会占用内存。
在做出决定时,需要考虑以上因素。 std::optional<A>
不涉及动态内存分配/释放,但您为此付出的代价可能是“{1}}内部浪费”的内存。使用std::optional<A>
进行大规模实例化和/或大型对象可能会非常浪费,特别是如果对象的大部分生命周期都处于空状态。
这意味着std::optional
的目的并非完全针对可选的长期存储。 std::optional
是本地使用的内容:例如:作为可选的本地值,函数的可选参数,可选的返回值。只要您没有大量实例化此类对象,长期使用也是可以的。
std::optional
不会浪费内存,但您为此付出的代价是动态内存分配/释放。
当然,所有权语义也大不相同。 std::unique_ptr<A>
是可复制的。 std::optional
是可移动的,但不可复制。