2012-03-06 8 views
5

例えば、この関数はfを次のように定義されて:あなたは、この一時的なint型への参照を割り当てるカント知っているようなぜ一時変数ではなく、ローカル変数の参照によって関数を返すことができますか? C++

int f(int x){return x;} 

int& rf=f(2);// this will give an error 

が、私はこのように私の関数fを再定義した場合:

int& f(int x){return x;} 
f(2);// so now f(2) is a reference of x, which has been destroyed 

私の質問は:どのようにコンパイラは、 statary(最初のケースのint)の後で破壊されるorary。一方、コンパイラはreturnの後にこのファイルが破壊されることを知っていますが、参照f(2)〜xを作成することができます。

+1

これはUBです(とにかく、参照にアクセスしています)。正気のコンパイラが警告します。 –

答えて

7

無効であることを確認することができますことは、コンパイラが検出するのは困難または不可能となる可能性があります。たとえば、次のように

int & f() 
{ 
    int x; 
    extern int & g(int & x); 

    // Does this return a reference to "x"? 
    // The compiler has no way to tell. 
    return g(x); 
} 

でも外部関数を呼び出すことなく、まだ返された参照がローカルにあるかどうかを知らせるために、複雑なプログラムの流れを解析することが困難なことができます。診断するために「単純なもの」とみなすものを定義しようとするのではなく、標準は診断を必要としません。良いコンパイラは、少なくとも単純なケースでは、警告を出すべきです。

非const参照に一時的にバインドするのは、コンパイラが簡単に検出できるものなので、標準では診断が必要です。

1

標準で指定されているように、関数からの一時変数への参照を返すのは未定義の動作です。間違って何

は、実際には関数の定義である:

int& f(int x) 
{ 
    return x; 
} 
0

それはあなたが戻っている参照がまだ有効なものを指します確認している場合を除き、参照によって返すことは良い考えではありません。

未定義の動作が予想されます。変数がローカルであるため、

、あなたはtehの参照がローカルへの参照を返す

+2

変数はローカルなので、無効であることを確認できます。 –

1

一時参照値をconst参照にバインドして、その寿命を延ばすことができます。それは未定義の動作であったとしても、だから、言語は、これを許可するしかない -

const int& rf=f(2); 
0

問題は、意味的にスタック上の変数、またはヒープなどの変数の間には差がないということです。 最初の例では、一時変数の参照をバインドしようとしているので、簡単なコンパイルエラーが発生します。これは言語によって禁止されている可能性があります。

+0

はい私はそれを理解しますが、なぜ2番目の例ではうまくいくのでしょうか?なぜヒープについて言及したのですか?ヒープについて何も言わなかった – AlexDan

+0

@AbdessamadBondヒープ上の変数への参照を返すので、2番目の例では動作しません。 ok(おそらくそれが悪いスタイルであっても)。意味的には、ヒープ上の変数とスタック上の変数に違いはありませんが、変数と一時的な値には違いがあります。 – cooky451

1

最初のコードスニペットを拒否するには、コンパイラは、非const参照に一時的に直接バインドできない単純なルールを適用します。

2番目を拒否するには、コンパイラは、参照によって返される関数の文を自動変数の名前(バイ値関数のパラメータを含む)にすることはできないというルールを適用する可能性があります。それは私にとってもかなり簡単なルールに見えます。

私は、標準がそのようにしていないことを明記していない理由を知りません。私はそれを有効に使うことは考えていませんが、おそらく最初の標準の時には実装やその他のことに過度の負担をかけるでしょう。あるいは、おそらく半分しか修正されておらず、気にする価値がないと感じられました(ダングリングリファレンスを作成するには他にもたくさんの方法があります。

標準で一般的に非const参照を一時的にバインドすることを止めないのは、それが問題な場合があるということです。例:ここでは

struct Foo { 
    static void set(Foo &f) { f.val = 0; } 
    int val; 
    int bar() { 
     set(*this); 
     return val; 
    } 
}; 

std::cout << Foo().bar() << "\n"; 

Foo()は一時的なものであり、そしてラインset(*this)を非const参照にバインドします(直接ではなく、それは一時的に参照する左辺値式*thisいくつかの回ではなく、他人を使用しています) 。ここには問題はありません。一時的なものは参考になります。したがって、一時的な一時的なものが何らかの非const参照にバインドされるのを防ぐために、言語が不必要に制限的になります。

関連する問題