std :: shared_ptr无法使用range

时间:2013-04-26 16:03:52

标签: c++ for-loop c++11 shared-ptr

我试图迭代一个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

1 个答案:

答案 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