[英]What's the lifetime of temporary objects in a range-for?
考慮這個課程:
class Foo
{
public:
~ Foo ()
{
std::cout << "~Foo\n";
}
typedef std::vector<std::string> Words;
const Words & words ()
{
return m_words;
}
private:
Words m_words = {"foo", "bar", "baz"};
};
C ++標准的第12.2節規定了臨時對象的生命周期。 我以為這沒關系:
for (auto w : Foo () .words ())
std::cout << w << "\n";
但事實並非如此
~Foo
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
[1] 10290 abort (core dumped) ./a.out
標准令我感到困惑。 為什么在循環運行之前調用~Foo
?
當前的標准在基於范圍的聲明[stmt.ranged]中說明了
基於范圍的聲明
for ( init-statementopt for-range-declaration : for-range-initializer )
語句
相當於{ init-statementopt auto &&__range = for-range-initializer ; auto __begin = begin-expr ; auto __end = end-expr ; for ( ; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } }
這意味着你的Foo().words()
僅用於賦值auto &&__range = Foo().words();
並且在代碼到達for循環之前臨時對象不會生效。
請注意,我復制了最新的C ++ 20草案 。 在C ++ 11中,代碼有點不同,但相關部分是相同的。
我認為答案是在定義范圍的方式和__range
綁定的方式中找到的。
[class.temporary] / 6 - 有三種情境可以在與完整表達結束時不同的時刻銷毀臨時對象。
- 第三個上下文是將引用綁定到臨時對象。 綁定引用的臨時對象或作為綁定引用的子對象的完整對象的臨時對象在引用的生命周期中仍然存在 ...
如果你改變for-loop
表達式直接綁定到子對象m_words
(假設它是公共的),那么Foo()
的生命周期將被擴展,以下將是有效的
for (auto w : Foo ().m_words)
std::cout << w << "\n";
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.