范围内的临时对象的寿命是多少?

时间:2019-01-01 19:28:08

标签: c++ c++11 for-loop temporary-objects

考虑此类:

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

2 个答案:

答案 0 :(得分:4)

当前标准在基于范围的语句[stmt.ranged] 中表示

  

基于范围的for语句
  // add event listener for the button (not the whole pop-up), to run ONCE only document.querySelector('button.action').addEventListener('click', listener, {once: true}); // FF50+, Ch55+ async function listener() { await browser.tabs.executeScript({file: 'content.js'}); const tabs = await browser.tabs.query({currentWindow: true, active: true}); browser.tabs.sendMessage(tabs[0].id, {command: 'message'}); } 声明
  等同于

// add listener only if it wasnt done before
if (!sessionStorage.getItem('runOnce')) {

  // keep track of previous attempts in sessionStorage
  sessionStorage.setItem('runOnce', 'true');      
  browser.runtime.onMessage.addListener(handleMessage);
}

function handleMessage(request, sender, sendResponse) {

  if(request.command === 'message'){
    console.log("Message from popup");

    // remove listern after the first run
    browser.runtime.onMessage.removeListener(handleMessage);
  }
}

这意味着您的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 } } 中使用,并且临时对象在代码到达for循环之前不存在。

请注意,我是从latest C++20 draft复制过来的。在C ++ 11中,代码有所不同,但是相关部分相同。

答案 1 :(得分:1)

我认为答案应以定义https://crudata.uea.ac.uk/cru/data/temperature/HadCRUT.4.6.0.0.median.nc的方式以及绑定到__range的内容来找到。

  

range-for -在三种情况下,临时变量在与完整表达式结束时不同的位置被销毁。

     
      
  • 第三个上下文是将引用绑定到临时对象时。引用绑定到的临时对象或引用绑定到的子对象的完整对象的临时对象在引用的生存期内一直存在 ...
  •   

如果您将for-loop表达式更改为直接绑定到子对象m_words(假设它是公共的),则Foo()的生存期将得到延长,以下将起作用< / p>

for (auto w : Foo ().m_words)
    std::cout << w << "\n";