簡體   English   中英

在構造函數中使用臨時作為默認參數

[英]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()) {}

我在這里有三個問題:

  1. 在最后一種情況下,foo的范圍是什么? 即使退出構造函數后,它是否仍然存在。 根據我的閱讀,如果將臨時對象分配給const引用,則會修改其生存期,在這種情況下,它將占用為其分配的引用的生存期。 默認參數(在這種情況下為foo)的生存期是多少?
  2. 我在MSVC中嘗試了第二個示例,但它沒有抱怨。 我還注意到,臨時文件的壽命仍在延長。 因此,我可以在構造函數退出后使用foo。 那是什么意思
  3. 我的方案要求以這種方式將默認參數傳遞給構造函數,而我將需要在構造函數中修改該參數(因此無法將其設為const)。 而且我還需要在構造函數退出后使用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

否則,只需忽略默認參數即可。 您還可以創建兩個重載來覆蓋不同的情況。

  1. 構造函數完成后, foo及其臨時變量都消失了。
  2. 這是不符合語言標准的MS擴展。
  3. 在這種情況下,請勿使用臨時默認值。 如果您需要能夠在構造函數完成后訪問它,則需要在調用構造函數之前自己創建對象,並通過引用將其傳遞。
  1. 在這種情況下(與大多數情況一樣),將直接綁定到引用的臨時綁定的生存期延長到引用的生存期。 因此,只要foo是有效的,即在構造函數的持續時間內,該臨時文件都是有效的。 當包含構造函數調用的完整表達式結束時,它將結束。

  2. MSVC有一個擴展,允許臨時對象綁定到非常量引用。 它不是標准的,其他編譯器也不支持。 除非您(並且將始終)僅為MSVC編碼,否則請不要使用它。

  3. 這取決於您實際想要實現的目標-您的問題中沒有足夠的信息來回答。 如果您需要它在構造函數退出后仍然存在,則需要提供一個具有適當生存期的實際對象。 您可以提供每個線程的靜態成員,例如:

     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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM