我有一个类,其中一个成员是动态分配的(只有在使用时才会分配)。
类似于这样的情况:
class A {};
class B {
A* aMember;
};
如何更好地替换 A*
: std::optional
还是 std::unique_ptr
?
什么时候应使用 std::optional
而不是 std::unique_ptr
?
我有一个类,其中一个成员是动态分配的(只有在使用时才会分配)。
类似于这样的情况:
class A {};
class B {
A* aMember;
};
如何更好地替换 A*
: std::optional
还是 std::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>
不涉及动态内存分配/释放,但您所付出的代价可能是在std::optional<A>
中存在潜在的“浪费”内存。对于大量实例化和/或大型对象使用std::optional
可能会非常浪费,特别是如果该对象在其生命周期中大部分时间处于空状态。
这意味着std::optional
的目的并非专门针对可选的长期存储。 std::optional
应该被用作本地:例如,可选的局部值、函数的可选参数、可选的返回值。长期使用也可以,只要您不要大量实例化此类对象。
std::unique_ptr<A>
不会浪费内存,但你为此付出的代价是动态内存分配/释放。
当然,所有权语义也非常不同。std::optional
是可复制的。std::unique_ptr
是可移动的,但不可复制。
unique_ptr
。 - underscore_d
std::optional
将跳过动态分配。这通常会导致更好的性能和更少的内存开销。如果aMember
只是为了能够为 null 而被动态分配,那么我的选择将是std::optional
。 - Guillaume Racicotstd::optional
。但请注意,与值一样,多态性也不起作用,例如您不能将A
的子类保存在可选项中。 - Guillaume Racicot