2013-04-26 33 views
6

Tôi đang cố gắng lặp qua đối tượng tạm thời trong một phạm vi cho vòng lặp. Dường như đối tượng được desctucted trước khi vòng lặp bắt đầu thực hiện. Đây có phải là hành vi tuân thủ tiêu chuẩn không? Tôi đang sử dụng gcc 4.8.std :: shared_ptr không hoạt động với phạm vi cho

#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'; 

    } 
} 

Kết quả là như sau:

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

Trả lời

13

, hành vi này là phù hợp.

mỗi đoạn 6.5.4/1 của C++ 11 Tiêu chuẩn:

Đối với một phạm vi dựa trên for tuyên bố của mẫu

for (for-range-declaration : expression) statement 

hãy phạm vi-init tương đương biểu thức được bao quanh bởi dấu ngoặc đơn

(expression) 

và cho một dải dựa trên for tuyên bố của mẫu

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

hãy phạm vi-init tương đương với chuẩn bị tinh thần-init-list. Trong mỗi trường hợp, một loạt trụ sở cho tuyên bố là tương đương với

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

Trong trường hợp của bạn, con trỏ chia sẻ trở lại được dereferenced, và đối tượng mà nó trỏ tới được ràng buộc với __range tham khảo. Tuy nhiên, bản thân con trỏ được chia sẻ không được sao chép, cũng không bị ràng buộc với tham chiếu kéo dài tuổi thọ của nó. Vì vậy, nó đi ra khỏi phạm vi. Là con trỏ được chia sẻ cuối cùng tham chiếu đến đối tượng nhọn, đối tượng cũng bị phá hủy.

Mọi thứ có lẽ đã khác nếu bạn đã trở lại đối tượng Test của bạn bằng giá trị, chứ không phải trở về một con trỏ chia sẻ:

Test func() { 
    return Test(); 
} 

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

    } 
} 

Bằng cách này, Test tạm thời được trả về bởi func() được ràng buộc với __range tham khảo, và tuổi thọ của nó được kéo dài để phù hợp với tuổi thọ của tham chiếu.

Dưới đây là live example.

+0

Hoặc chỉ cần lưu shared_ptr làm địa phương: http://ideone.com/U0eC8l –

+0

Khác với lựa chọn đơn giản để giữ dụ 'shared_ptr' trong phạm vi cục bộ, có cách giải quyết nào được đề nghị không? – epl

Các vấn đề liên quan