2

ここから、関数によって値によって返されるオブジェクトからconst参照を作成できることを学びました。しかし今、私は自分自身に問いかけました。安全で、将来の関数呼び出しのスタックによって上書きされないように、このオブジェクトをどこに配置するのでしょうか。

このコードを考えてみましょう:

#include <iostream>
using namespace std;

struct A{};

A returnsmt(){
    int avariable;
    cout<<"returnsmt stack: "<<&avariable<<endl;
    return A();
}

const A& proxyreturnsmt(){
    int avariable;
    const A& middle=returnsmt();
    cout<<"proxyreturnsmt stack: "<<&avariable<<" A ptr: "<<&middle<<endl;
    return middle;
}

int main(){
    int avariable;
    const A& a=proxyreturnsmt();
    cout<<"main stack: "<<&avariable<<" A ptr: "<<&a<<endl;
}

mainさて、スタックのオブジェクトから参照を作成することを知っていることさえ実現可能ではないので、それ自体の空きスタックバケットに隠しポインタを渡すというトリックはあり得ません。g++の次のコードは次のように出力します。

returnsmt stack: 0x7fff3718bc0c
proxyreturnsmt stack: 0x7fff3718bc28 A ptr: 0x7fff3718bc2f
main stack: 0x7fff3718bc4c A ptr: 0x7fff3718bc2f

したがって、スタックが下向きに成長すると、オブジェクトがある場所は事実上スタックであるように見えproxyreturnsmtます。この参照を取得した後、たとえば、と呼び出して、古いスタックを新しい使用法のfunction_with_big_stack_allocために確実に再利用する場合、どうして問題が発生しないのでしょうか。proxyreturnsmt

4

1 に答える 1

0

プログラムは未定義の動作を示します。では、一時オブジェクトにproxyreturnsmtバインドします。middleその一時オブジェクトの存続期間はmiddle、スコープ外になるまで延長されます。

middle次に、 ;への参照を返します。ただし、関数が戻ると、それが参照するオブジェクトは破棄されます。したがって、を呼び出した結果にmainバインドするのは、ぶら下がっている参照です(それが参照するオブジェクトはもう存在しません)。aproxyreturnsmta

参照を使用しようとすると(存在しなくなった参照オブジェクトのアドレスを取得することにより)、プログラムは未定義の動作を示します。

于 2012-04-13T18:12:29.053 に答える