考虑与不能直接存储的成员,例如一类,因为它不会有一个默认的构造函数,封装类的构造函数没有足够的信息来创建它:间接成员RAII:unique_ptr还是可选的?
class Foo
{
public:
Foo(){} // Default ctor
private:
/* Won't build: no default ctor or way to call it's
non-default ctor at Foo's ctor. */
Bar m_bar;
};
显然,m_bar
需要以不同方式存储,例如通过指针。一个std::unique_ptr
似乎好一些,不过,因为它会自动销毁它:
std::unique_ptr<Bar> m_bar;
它也可以使用std::experimental::optional
,虽然:
std::experimenatl::optional<Bar> m_bar;
我的问题是:1。什么是权衡?和2.建立一个自动化他们之间选择的类是否有意义?
具体来说,看着exception guarantees for the ctor of std::unique_ptr
和exception guarantees for the ctor of std::experimental::optional
,它似乎很清楚,前一定要进行动态分配和释放 - 运行速度不足,在某些(对齐的)内存缓冲,后者店的东西 - 尺寸方面的缺点。这些是唯一的折衷?
如果这确实是权衡,并鉴于这两种类型的共享足够的接口(构造函数,operator*
)的,它是有意义的东西像
template<typename T>
using indirect_raii = typename std::conditional<
// 20 - arbitrary constant
sizeof(std::experimental::optional<T>) >
20 + sizeof(std::exerimental::optional<T>)sizeof(std::unique_ptr<T>),
std::unique_ptr<T>,
std::experimental::optional<T>>::type;
(注意它们之间自动进行选择:有一个question discussing the tradeoffs between these two为返回类型,但问题和答案专注于每一个传递的功能,这是不相关的,这些私有成员的用户)
谢谢。对于你的第一点,我猜'shared_ptr'也是一个竞争者呢? –
是的,我一开始也这么认为,但是语义从根本上发生了变化,对吧?由于它不复制底层数据。如果你只是用'const'类型来使用它,那么我想它是可以的。但你不想如将另一个数据成员添加到您的类中,然后程序的某个其他部分突然从'optional'切换到'shared_ptr'并打破一些代码。 –