Std::shared_ptr不能使用range for

std::shared_ptr not working with range for

本文关键字:range for ptr shared Std 不能      更新时间:2023-10-16

我正在尝试迭代一个范围内的临时对象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

,行为是兼容的。

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等价于带括号的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';
  }
}

这样,func()返回的Test临时值绑定到__range引用,并且它的生存期被延长以匹配引用的生存期。

下面是一个的实例