2011-12-01 27 views
3

"参照時の参照"または "参照による関数の引数の渡しまたはポインタ渡し"という質問は何度も尋ねられます。しかし、私はいくつかの機会に私が読んだ印象を持っています。「オブジェクトをポインタで関数に渡す必要があります。最後の文が完全に正しいかどうか、誰かが説明し正当化することができますか?関数内の参照またはポインタとしてのオブジェクトの受け渡し

つまり、参照によってオブジェクトを変更することはできませんか?

答えて

4

あなたにどのようなポインタのポイントを変更したい場合は別のメモリ位置からオブジェクトを移動するときは、例えば、二重のポインタとしてオブジェクトを渡す必要があります。

void foo (obj **x) { 
    delete *x; 
    obj *y = (obj *) some_new_address; 
    *x = y; // change what x points to 
} 
... 
obj *x = new obj(); 
foo(&obj); 
// obj now points to another location 

することができます参照して」それをしないでください。

+6

参照でポインタを渡すことができます: 'void foo(obj *&x)' –

+0

でも、まだポインタを渡しています。ポインタと参照のセマンティクスを混在させると、IMOが非常に混乱することがあります。 –

+4

@BlagovestBuyukliev:ハァッか。ここには何も混じっていません。あなたはポインタを参照しています。これは、ポインタへのポインタを持つよりもずっと簡単です。 – GManNickG

0

参照とポインタの両方でオブジェクトを修正できます。変更したくない場合は、const修飾子を使用できます。

2

あなたが引用した文章は規範的です。つまり、あなたが何をすべきかを教えてくれるものであり、できないものではありません。したがって、それはスタイルの問題であり、議論の対象となります。私は個人的にそれを受け入れません。

オブジェクトを(const)参照で確実に変更することは可能です。

0

変数をoutパラメーターとして渡すには、参照とポインターとして渡すことができます。変数がスコープよりも長く存続する必要がある場合にのみ、ポインタを使用してみてください。たとえば。関数から呼び出し先にポインタを返します。

場合によっては、スタックにメモリを割り当てることができない場合は、ポインタを使用してヒープにメモリを割り当てます。やはり、ポインターまたは参照によってoutパラメーターとして関数にポインターを渡すことができます。

1

もちろん、参照によってオブジェクトを変更することは可能です。たぶんあなたが引用した文章はCについてのものでしたが、それは参照がありませんか?

ガイドラインは、このようなものです:

  • 引数を変更すると、発信者は、それを提供ポインタ渡し(なしオブジェクトに対してNULL、0またはnullptrを渡す)ない場合があります。
  • 引数を変更したい場合はオブジェクトを関数に渡す必要があります。
  • 呼び出し側が引数を変更したくない場合は、constポインタを渡します。
  • それ以外の場合は、オブジェクトがconst参照渡しで高価な場合は、値渡しします。
  • 新しい機能 - 関数内で引数をコピーする(たとえば、フィールドを初期化するためにコンストラクタ内に文字列を渡す)場合は、C++ 11準拠のコンパイラ(移動コンストラクタのサポート)を使用して値渡しを行います。
4

便宜上、関数によって変更されたパラメータを「アウト・パラメータ」と呼びます。

Out-paramsは非const参照として渡すことができます。ない技術的な理由はありません。例えば、標準ライブラリでは、std::swapは参照によって2つのパラメータをとり、両方を変更します。

私は過去に、スタイルガイドのルールとして、out-paramsを参照ではなくポインタで渡す必要があることを見てきました。この背後にある動機は、[*]と表示されている関数呼び出しがの場合、オブジェクトを値で渡してオブジェクトを変更しないままにしたいということです。これにより、関数が実際に何をしているのかを調べることなく、呼び出しコードを見るだけで、コードについて簡単に判断することができます。たとえば:

int foo(int a) { 
    return a + 1; 
} 
int bar(int &a) { 
    return ++a; 
} 

は今、int i = 0;与えられ、通話foo(i)bar(i)はまったく同じに見えますが、他方は参照渡しiを変更するために使用するのに対し、そのうちの一つは、素敵な、シンプルなC関数のように振る舞います。

一部の人[*]は、これらの異なるものが呼び出しサイトで明らかに異なるものにしたいので、彼らはそれを明確にi[**]を変更することができることを行うためにbar(&i)を書くことを好むだろう。基本的には、C++は関数のパラメータとして非const参照を全く持たないことを好みます。

これらの人々がしたいことに必ずしも間違っていることはありません。たとえば、std::swapの場合は、常にstd::iter_swapを使用してそれに固執することができます。しかし、ほとんどのC++スタイルのガイドにはそのようなルールはありません。実際に

[*]例えばCプログラマ

[**]aがで-PARAMの両方とアウトのparamである私のbar機能、インチ彼らの好みの関数int bar(int *pa);は、技術的にはout-paramを持っていませんが、便宜のために参照番号としてpa(つまり、i)の参照を参照し、その意味を誰もが知っています。

関連する問題