2013-04-26 50 views
6

我正在嘗試迭代循環範圍內的臨時對象。它看起來像對象在循環開始執行之前得到了desctucted。這是一種符合標準的行爲嗎?我正在使用gcc 4.8。std :: shared_ptr不適用於範圍

#include <iostream> 
#include <vector> 
#include <memory> 

struct Test: std::vector<int> { 
    Test(): std::vector<int>{1,2,3} { 
    std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 

    ~Test() { 
    std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 
}; 

std::shared_ptr<Test> func() { 
    return std::shared_ptr<Test>(new Test); 
} 

int main() { 
    for (const auto &obj: *func()) { 
    std::cout << obj << '\n'; 

    } 
} 

結果如下:

Test::Test() 
Test::~Test() 
21770300 
0 
33 
0 
0 
0 
3 

回答

13

,其行爲符合。

每一段的C++ 11標準的6.5.4/1:

對於形

for (for-range-declaration : expression) statement 

的基於範圍的for語句讓範圍-INIT相當於到括號括起來的表達式

(expression) 

並且對於基於範圍的形式

for (for-range-declaration : braced-init-list) statement 

for聲明讓範圍-INIT等同於支撐,初始化列表在每種情況下,範圍爲基礎的語句相當於

{ 
    auto && __range = range-init; 
    for (auto __begin = begin-expr, 
     __end = end-expr; 
     __begin != __end; 
     ++__begin) { 
     for-range-declaration = *__begin; 
     statement 
    } 
} 

在你的情況下,返回的共享指針被解除引用,並且對象它指向被綁定到__range參考。但是,共享指針本身不會被複制,也不會綁定到可延長其生命週期的引用。因此,它超出了範圍。作爲引用指向對象的最後一個共享指針,對象也會被銷燬。

事情會有所不同,如果您已經通過返回值的Test的對象,而不是返回一個共享指針:

Test func() { 
    return Test(); 
} 

int main() { 
    for (const auto &obj: func()) { 
    std::cout << obj << '\n'; 

    } 
} 

這樣,通過func()返回Test臨時綁定到__range參考,並其使用壽命延長至與參考的壽命相匹配。

這是live example

+0

或簡單地將shared_ptr作爲本地存儲:http://ideone.com/U0eC8l – 2013-04-26 22:50:09

+0

除了在本地範圍內保存'shared_ptr'實例的簡單選擇之外,是否有任何推薦的解決方法? – epl 2017-01-18 23:52:33

相關問題