我试图迭代一个for循环范围内的临时对象。看起来这个对象在循环开始执行之前被破坏了。这是符合标准的行为吗?我使用的是gcc 4.8。
#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
答案 0 :(得分:14)
是,行为符合规定。
根据C ++ 11标准的第6.5.4 / 1段:
对于表单
的基于范围的for
语句for ( for-range-declaration : expression ) statement
让 range-init 等同于括号
所包围的表达式( expression )
以及表单
的基于范围的for
语句for ( for-range-declaration : braced-init-list ) statement
让 range-init 等同于 braced-init-list 。 在每种情况下,基于范围的for语句等同于
{ 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';
}
}
这样,Test
返回的func()
临时值绑定到__range
引用,其生命周期延长以匹配引用的生命周期。
这是live example。