介紹
假設有一個Container
存盤Widget
物件的類。有一個迭代器類負責導航這樣的容器。這個迭代器類 ( MyIterator
) 在其建構式中接受一個對向量的常量參考Stuff
,它需要迭代容器中的正確元素。代碼可能如下所示:
class MyIterator
{
public:
MyIterator(
const Container& container, // Container to be navigated
const std::vector<Stuff>& vec) // Parameter which controls the behaviour of the iteration
: container(container)
, stuffVector(vec)
{}
...
private:
const Container& container;
const std::vector<Stuff>& stuffVector;
};
問題
我很好奇rvalue與 const 參考的系結,以及生命周期擴展如何作業。
雖然vec
可以系結到臨時rvalue ,但一旦rvalue的生命周期結束,這將導致stuffVector
成為一個懸空參考。所以像這樣旨在為物件創建迭代器的代碼是錯誤的:myContainer
MyIterator it = {myContainer, {stuff1, stuff2, stuff3}};
// Here it.stuffVector is a dangling reference!
閱讀cppreference中臨時物件的生命周期延長我發現:
每當參考系結到臨時物件或其子物件時,臨時物件的生命周期就會延長以匹配參考的生命周期(...)此生命周期規則有以下例外:(...)
- 函式呼叫中參考引數的臨時系結一直存在,直到包含該函式呼叫的完整運算式結束:如果函式回傳一個參考,該參考比完整運算式的壽命長,則它成為一個懸空參考。
問題
突出顯示的部分讓我想到了這個問題:這段代碼能否成功獲得內容的過濾版本myContainer
?
std::vector<Widget> filteredWidgets;
std::copy_if (
MyIterator{myContainer, {stuff1, stuff2, stuff3}},
MyContainer.end(),
std::back_inserter(filteredWidgets),
[&](Widget w) { return ...; });
第二個引數是rvalue,因此存在創建懸空參考的危險,但我對檔案的理解是rvalue的生命周期將延長到 rvalue 結束std::copy_if
,所以沒問題。哪一個?
注意:我知道問題和設計,如前所述,可能看起來有點奇怪,但它的靈感來自我在野外發現的真實代碼。我對延長壽命的限制感興趣,而不是想出不同的設計,這會使問題變得無關緊要。
uj5u.com熱心網友回復:
是的,整個std::copy_if
呼叫是完整的運算式,只有在呼叫回傳后臨時std::vector<Stuff>
才會被銷毀。
這與按值函式引數不同。如果建構式采用 astd::vector<Stuff>
而不是 a const std::vector<Stuff>&
,那么當建構式回傳時,物件是存活那么久還是立即銷毀將由實作定義。
完整運算式是[intro.execution]/5中列出的運算式之一。任何特定情況(例如未評估的運算元、立即呼叫等)都不適用于此處,因此不適用,相關條件是:
一個運算式,它不是另一個運算式的子運算式,也不是完整運算式的一部分。
呼叫運算式是該copy_if
陳述句中唯一適用的(在 lambda 主體之外)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/488654.html