2016-04-17 20 views
4

私は、一時的に参照するconstの参照を返す関数の宣言についていくらか混乱します。次のコードconst参照を返す

#include <string> 
#include <iostream> 

using namespace std; 

const string& foo() { 
    return string("foo"); 
} 
string bar() { 
    return string("bar"); 
} 

int main() { 
    const string& f = foo(); 
    const string& b = bar(); 
    cout << b; 

} 

方法foobarの違いは何ですか?で

なぜfooが私にwarning: returning reference to local temporary object [-Wreturn-stack-address]を与えるのですか?テンポラリのコピーはconst string& f = foo();に作成されていませんか?

答えて

6

string("foo")は、"foo"という値を含むタイプstd::stringのオブジェクトを関数内にローカルに作成します。このオブジェクトは、関数の最後に破棄されます。したがって、コードがその関数を離れると、そのオブジェクトへの参照を返すことは無効になります[1]。したがって、mainでは、その文字列への有効な参照は決してありません。 fooのローカル変数を作成した場合も同様です。

リファレンスを返すのは、コピーを作成せず、リファレンス(string &f = foo()は初期化)を初期化するということは、元のオブジェクトのコピーを作成しないということです。コードがmainに戻った時点で既に無効です。多くの場合、参照は「同じものの別の名前」とみなすことができます。

参照されるオブジェクトの寿命(つまり、実際のオブジェクトの「エイリアス名」が参照する)は、参照変数(この場合はf)よりも長く存続する必要があります。

barの場合、コードはreturn string("bar");の一部としてコピーを作成します。これは、オブジェクトを参照せずに返すため、つまりオブジェクトをコピーして動作させるためです。

[1] pedantically、まだ関数の中にあるが、関数内で作成したコードの終わりの後に、コンパイラが関数で作成されたオブジェクトの破壊に対処するために導入したコードのビット。

+1

キーは、この場合、 'const'は存続期間を延長しないということです。 –

0

いずれの場合も、文字列オブジェクトは初期化され、スタックに割り当てられます。 関数から戻ると、関数を含むメモリセグメントは無関係になり、その内容はオーバーライドされる可能性があります。

ファンクションの相違点: barファンクションの違いは、その内部で作成された文字列インスタンスのコピーを戻します。

foo関数は、その内部で作成された文字列インスタンスへの参照を返します。 つまり、一時的なメモリセグメントにある戻り値への暗黙のポインタを返します。これが警告の理由です。

+0

文字列オブジェクト自体は、ヒープ上ではなくスタック上に作成されます。 –

+0

@Mats Petersson、ご意見ありがとうございます。私はコースのスタックを意味し、ヒープは意味しません。 – drorco

+0

自動保存期間があります。物理的な(仮想的な)記憶場所がその記憶域を後退させるために利用される可能性があるという仮説は立てない。 「スタック上」は誤解を招き、必ずしも正確ではありません。 –

0

は、あなたがそれを聞いたconst string& f = foo();

に作成された一時のコピーではないですか?

参照にconstを追加すると、初期化された一時的なライフタイムが参照自体の存続期間まで延長されることがよくあります。コピーはありません。

ここでもそうではありません。参照にバインドしているオブジェクトは、関数の終わりにスコープから外れ、他のすべてのオブジェクトよりも優先されます。

あなたはぶら下がっている参照を返しています。期間。

0

fooは、ローカルの一時的な オブジェクト[-Wreturn-stack-address]への参照を返します。

あなたはfoo()内部の一時的な文字列オブジェクトを作成している、とあなたはすぐに(参照ダングリング)スコープの外に出ます、そのオブジェクトへの参照を返しています。

const string& foo() { 
    return string("foo"); // returns constant reference to temporary object 
}       // object goes out of scope 

bar()かなり異なっている:

string bar() {    
    return string("bar"); // returns a copy of temporary string 
} 
... 
const string& b = bar(); // reference an rvalue string 

メソッドfooとbarの違いは何ですか?

foo()bar()は、一時的な文字列オブジェクトのコピーを返しながら定数(ダングリング)の参照を返します。