2

このコードがCode::blockで正常に実行されるのはなぜですか。IDBはただ報告します

警告:「ローカル変数'tmp'への参照が返されました」、

しかし、結果「helloworld」を正常に出力します。

#include <iostream>
#include<string>
using namespace std;

const string &getString(const string &s)
{
    string tmp = s;
    return tmp;
}

int main()
{
    string a;
    cout<<getString("hello world")<<endl;
    return 0;
}
4

6 に答える 6

2

関数を終了すると、すべてのローカル変数が破棄されます。への参照を返すことによりtmp、すぐに存在しなくなるオブジェクト (つまり、技術的には、内容が意味を持たなくなったメモリ領域のアドレス) への参照を返すことになります。

このようなダングリング参照にアクセスすると、いわゆる「未定義の動作」が呼び出されます。悲しいことに、「通常どおりの動作」は「未定義の動作」の一種です。ここで発生する可能性があるstd::stringのは、(ヒープからメモリを取得する大きな文字列とは対照的に) 小さな文字列用に小さな静的バッファーを保持し、getStringこの文字列が占有するスタック領域を離れるとゼロにされないため、まだ機能しているように見えることです。 .

デバッグ ビルドを試みるか、その間に別の関数を呼び出すと (これによりスタック スペースが実質的に上書きされます)、機能しなくなります。

于 2011-09-21T12:41:06.450 に答える
1

未定義の動作を引き起こしています。その場合に何が起こるかは標準ではわかりませんが、コンパイラはそれを検出しました。

于 2011-09-21T12:40:05.703 に答える
1

tmpから戻った瞬間に消えますgetString。返された参照の使用は未定義の動作であるため、何が起こる可能性があります。

コードを修正するには、文字列を値で返します。

string getString(const string &s)
{
...
于 2011-09-21T12:41:26.200 に答える
0

一時オブジェクトの割り当ては解除されますが、何かが書き換えるまで、その内容はスタックに残ります。関数を呼び出してから返されたオブジェクトを出力するまでの間に、いくつかの関数を呼び出してみてください。

const string& garbage = getString("Hello World!");
callSomeFunctionThatUsesALotOfStackMemory();
cout<< garbage << endl;
于 2011-09-21T13:05:07.813 に答える
0

本気ですか?セグメンテーション違反が発生するはずです (ほとんどのプラットフォームでは gcc で発生します)。そのコードにはエラーが含まれており、「運が良ければ」それが機能する場合は、カーペットの下にある厄介なバグをブラッシングしています。

つまり、戻り先のコンテキストで有効な新しい文字列を作成するのではなく、古い破壊されたオブジェクトへのポインターが返されます。これは悪いことです。const string getString...関数の戻り値の型の宣言として機能します。

于 2011-09-21T12:42:36.673 に答える
0

ご覧のとおり、以下のコード例は、goodByeString() を呼び出すことでわずかに変更されています。他の回答がすでに指摘したように、tmp と呼ばれる getString の変数はローカルです。関数が戻るとすぐに、変数はスコープ外になります。スタックに割り当てられているため、関数が戻ったときにメモリは引き続き有効ですが、スタックが再び大きくなるとすぐに、tmp が存在するメモリのこの部分が別のもので書き換えられます。次に、 a への参照にガベージが含まれています。

ただし、参照によって返されないため b を出力することにした場合でも、内容は有効です。

#include <iostream>
#include<string>
using namespace std;

const string &getString(const string &s)
{
  string tmp = s;
  return tmp;
}

string goodByeString(const string &s)
{
  string tmp = "lala";
  tmp += s;
  return tmp;
}

int main()
{
   const string &a = getString("Hello World!\n");
   string b = goodByeString("ciao\n");
   cout << a << endl;
   return 0;
}
于 2011-09-21T17:53:45.187 に答える