7

ループの範囲で一時オブジェクトを反復処理しようとしています。ループの実行が始まる前に、オブジェクトが破棄されたようです。これは標準に準拠した動作ですか? 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
4

1 に答える 1

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その有効期間は参照の有効期間と一致するように延長されます。

これが実際のです。

于 2013-04-26T16:10:48.837 に答える