[英]Use a temporary as default argument in constructor
在C ++中,我們可以將對象分配給非const引用。 所以這有效:
Foo &foo = Foo();
但是,C ++不允許將臨時變量分配給非const引用。 因此,這是不允許的:
Bar::Bar(Foo &foo = Foo()) {}
但這是允許的
Bar::Bar(const Foo &foo = Foo()) {}
我在這里有三個問題:
提前致謝。
在最后一種情況下,
foo
的范圍是什么?
foo
是一個構造函數(同樣適用於常規函數)參數,因此,它的生存期在包含對構造函數的調用的完整表達式結束時結束 。 感謝aschepler !
默認參數(在這種情況下為foo)的生存期是多少?
通過將默認參數綁定到Foo const& foo
來延長默認參數的壽命,因此其壽命將與其綁定的引用的壽命相匹配,即直到構造函數體退出。
我在MSVC中嘗試了第二個示例,但它沒有抱怨。
如果將警告級別設置為/W4
,它將執行此操作; 在這種情況下,它會警告您正在使用非標准擴展名。 AFAIK,語義與前面的情況相同。
我的方案要求以這種方式將默認參數傳遞給構造函數,而我將需要在構造函數中修改該參數(因此無法將其設為const)。 而且我還需要在構造函數退出后使用foo。
這取決於您是否要將其保存為Bar
成員。 如果是前者,請使用右值引用並移動參數
Bar::Bar(Foo&& foo = Foo()) : f_(std::move(foo)) {} // f_ is a member of type Foo
否則,只需忽略默認參數即可。 您還可以創建兩個重載來覆蓋不同的情況。
foo
及其臨時變量都消失了。 在這種情況下(與大多數情況一樣),將直接綁定到引用的臨時綁定的生存期延長到引用的生存期。 因此,只要foo
是有效的,即在構造函數的持續時間內,該臨時文件都是有效的。 當包含構造函數調用的完整表達式結束時,它將結束。
MSVC有一個擴展,允許臨時對象綁定到非常量引用。 它不是標准的,其他編譯器也不支持。 除非您(並且將始終)僅為MSVC編碼,否則請不要使用它。
這取決於您實際想要實現的目標-您的問題中沒有足夠的信息來回答。 如果您需要它在構造函數退出后仍然存在,則需要提供一個具有適當生存期的實際對象。 您可以提供每個線程的靜態成員,例如:
class Bar { static thread_local Foo ctor_default_foo; public: Bar(Foo &foo = ctor_default_foo) {} };
注意,這當然意味着一個線程使用默認參數創建的所有對象都將共享相同的Foo
對象。 如果每個Bar
對象都需要一個新對象,則必須更改設計。 但是要告訴您如何操作,我們需要更多地了解實際用例。
我的方案要求以這種方式將默認參數傳遞給構造函數,而我將需要在構造函數中修改該參數(因此無法將其設為const)。 而且我還需要在構造函數退出后使用foo。 什么是最適合這種情況的設計?
您可以在Bar
創建一個optional<Foo>
,如下所示:
struct Bar
{
Bar() : optionalFoo(boost::in_place()), foo(*optionalFoo) {}
Bar(Foo& f) : foo(f) {}
Bar(Bar const&) = delete; // Compiler generated one is incorrect
private:
boost::optional<Foo> optionalFoo;
Foo& foo;
};
但是,可以選擇擁有其數據的類會變得棘手,特別是在涉及復制/移動時。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.