7

誰かが以下がバグであることを確認し、その理由を説明できますか? 知っていると思いますが、詳細は不明です。(私の実際の問題は、int ではなく、enum のベクトルに関係していましたが、問題にはならないと思います。) 次のコードがあるとします。

std::vector<int> f (void) {
  std::vector<int> v;
  v.push_back(5);
  return v;
}

void g (void) {
  const int &myIntRef = f()[0];
  std::cout << myIntRef << std::endl;
}

f の戻り値がスタックのどこにも保存されないため、myIntRef はすぐにダングリング リファレンスになるということは正しいでしょうか?

また、以下は有効な修正ですか、それともまだバグですか?

  const int myIntCopy = f()[0];  // copy, not a reference

つまり、0番目の要素がコピーできるようになる前に、f()の戻り結果が捨てられているのでしょうか?

4

2 に答える 2

11

それはバグです。完全な式の最後で、const int &myIntRef = f()[0];一時ベクトルが破棄され、メモリが解放されます。後で を使用すると、myIntRef未定義の動作になります。

状況によっては、一時オブジェクトへの参照をバインドすると、一時オブジェクトの有効期間が延長されることがあります。これはそのようなケースの 1 つではありません。コンパイラは、によって返された参照std::vector<int>::operator[]が一時的なものの一部なのか、int静的なストレージ期間を持つ への参照なのか、またはその他のものなのかを認識せず、寿命を延長しません。

于 2013-03-14T13:42:25.973 に答える
2

はい、実際に行うのは間違ったことです。電話すると:

return v;

オブジェクトの一時コピーvが作成されており、

const int &myIntRef = f()[0];

この一時コピーの最初の要素で参照を初期化します。この行の後、一時コピーは存在しなくなります。つまり、これmyIntRefは無効な参照であり、 of を使用すると未定義の動作が発生します。

あなたがすべきことは次のとおりです。

std::vector<int> myVector = f();
const int &myIntRef = myVector[0];
std::cout << myIntRef << std::endl;

これは(コピーエリシオンのおかげで)代入演算子を使用して、コピーを作成せずmyVectorに使用してオブジェクトを初期化します。この場合、参照の有効期間はオブジェクトの有効期間と同じであるため、完全に有効なコードになります。vvmyVector


そしてあなたの2番目の質問に:

「また、以下は有効な修正ですか、それともまだバグですか?」

 const int myIntCopy = f()[0];  // copy, not a reference

はい、これは別の可能な解決策です。f()[0]一時コピーの最初の要素にアクセスし、その値を使用してmyIntCopy変数を初期化します。v返された byのコピーはf()、少なくとも式全体が実行されるまで存在することが保証されています。C++03 標準 12.2 一時オブジェクト §3を参照してください。

一時オブジェクトは、それらが作成されたポイントを (レキシカルに) 含む完全な式 (1.9) を評価する最後のステップとして破棄されます。

于 2013-03-14T13:46:16.093 に答える