考慮與不能直接存儲的成員,例如一類,因爲它不會有一個默認的構造函數,封裝類的構造函數沒有足夠的信息來創建它:間接成員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'並打破一些代碼。 –