2011-12-10 11 views
4

C++コードの簡単なリターンで:安全なC#ではないC++、ポインタ/参照

person* NewPerson(void) 
{ 
    person p; 
    /* ... */ 
    return &p; //return pointer to person. 
} 

C#コード:

person NewPerson() 
{ 
    return new person(); //return reference to person. 
} 

私はこの権利を理解していれば、C++の例では、OKではありませんpので スコープの外に行くと、機能は野生のポインタ(ダングリングポインタ)を返します。

C#の例は、匿名の新しい人物が参照がある限り、そのスコープ内にとどまるため、OKです。 (呼び出す関数は1つを取得します)

私はこの権利を得ましたか?

+2

あなたは[リンゴをオレンジと比較しています!](http://thisisindexed.com/wp-content/uploads/2011/11/card3052-380x232.jpg) –

+1

多分、しかし両方とも果実です。 :) – Niklas

答えて

2
person* NewPerson(void) 
{ 
    person p(); 
    /* ... */ 
    return &p; //return pointer to person. 
} 

pを実行し、次回はpersonではない、most vexing parseを参照してください。そのため、コンパイルエラーが発生します。残りについては

、はいあなたは正しいです。

1

C++では、 'p'はスタック上に存在するため、関数が返ってくるとclobberedになります。 C#では、ガベージコレクタは、最後の参照が失われるまで、ガベージコレクタがそれを壊さないことを知っています。

(緩くここで使用されている「クロバー」...:P)

+0

はい私はclobberedを理解していません:) – Niklas

+0

私はより技術的であったはずです:)。私はちょうどそれがもはや有効にアクセス可能な方法で存在しないことを意味しました。それが書かれるまで、オブジェクトはそれがあった場所にまだ存在しますが、変数がスコープ(C++バージョン)から外れると、オブジェクト(つまり、すぐに上書きされます。 – Corbin

2

この例のスコープ規則は似ていますが、返された値が何かに割り当てられている場合、C#で、それはゴミが長いとして収集されることはありません何かがその参照を保持しているので。それが何かに割り当てられていない場合は、何もそれへの参照を保持していないし、それはゴミが収集されるコレクタは

0

私はこの権利を得ましたか?

はい。

BTW:C++ person p();関数を宣言し、personのデフォルトのctorを呼び出しません。人pを書くだけです。

0

関数が終了すると破棄される一時的な参照を返すので、これはC++では機能しません。ヒープ上にnew人を作成してから、それを参照する必要があります。

+0

人の代わりに人p()との間違いに加えて、p - pは一時的なオブジェクトではありません(C++の言葉では)。 – Simon

+0

申し訳ありませんが正しい - 私自身の答えを今投票しているような気がします:O – Ell

1

はい、正しいと思います。

しかし、C++で、あなたは本当にこの

person NewPerson() 
{ 
    person p; 
    /* ... */ 
    return p; //return person. 
} 

好きですし、コール

person x = NewPerson(); 

にコンパイラは、戻り値のコピーを最適化することをかなり確実だろう。

+0

OKですが、それはスピードでは一般化されません。ポインタが返される方が速いからです。 (あるいは、おそらくC++の良いオプションが因数分解関数を作っています) – Niklas

+0

この特殊なケースでは、言語は特に、コンパイラが戻り値のコピーを省略し、 'x'の適切な場所に構築することを可能にします。ほとんどのコンパイラはこれを利用しています。 –

+0

OKだから、新しい人へのポインタを返したのと同じ速度になりますか? – Niklas

4

「p」が有効範囲外になり、関数が無効なポインタを返すため、C++の例はokではありません。

正しい。

匿名の「新しい人物」は参照がある限り、その範囲内にとどまるため、C#の例はokです。

これは多かれ少なかれ正確ですが、あなたの専門用語はあまり正しくありません。 C#でのの範囲は、の修飾されていない名前を使用できるテキストの領域です。です。ここのオブジェクトには名前がありません。 生涯は、格納場所が有効であることが保証されているランタイムの期間であるです。スコープと有効期間が接続されています。コントロールがスコープに関連付けられたコードを残すとき、そのスコープ内で宣言されたローカルのライフタイムは通常終了することができます。コントロールがそのスコープ内にある時よりも、ローカルの生存期間が長くなったり短くなったりする状況があります。

また、生き続けるPersonオブジェクトへの参照はではありません。参照先はルーテッドでなければなりません。お互いを参照するが、そうでなければ到達不能な2つのPersonオブジェクトを持つことができます。それぞれが参照を持っているという事実は、それらを生かしていない。参照の1つは根づかなければなりません。

関連する問題