2012-04-20 14 views
70

どのような状況で、この性質のコードをC++で使用したいですか?C++での参照でポインタを渡す理由は?

void foo(type *&in) {...} 

void fii() { 
    type *choochoo; 
    ... 
    foo(choochoo); 
} 
+0

ポインタを返す必要がある場合は、戻り値を使用することをお勧めします。 – littleadv

+5

理由を説明できますか?この賞賛はあまり役に立ちません。私の質問はかなり合法です。これは現在、プロダクションコードで使用されています。なぜ私は完全に理解していない。 –

+1

Davidはそれを非常にうまくまとめます。ポインタ自体が変更されています。 – chris

答えて

111

ポインタが指しているオブジェクトではなくポインタを変更する必要がある場合は、参照によってポインタを渡したいと思うでしょう。

これは二重のポインタが使用される理由と同様です。ポインタへの参照を使用することは、ポインタを使用することよりもわずかに安全です。

+11

ポインタのポインタと似ていますが、参照渡しセマンティクスのインダイレクションのレベルは1つ少なくなります。 –

+1

それは正確です:) –

+0

私は時々あなたは参照によってポインタを返すことを追加したいと思います。たとえば、動的に割り当てられた配列にデータを保持するクラスがあり、このデータへの(一定でない)アクセスをクライアントに提供したい場合です。同時に、クライアントがポインタを介してメモリを操作できるようにする必要はありません。 –

7

私は、渡されたポインタにメモリを割り当てると、私には私の会社「オブジェクトは」STL

それは素敵ではありません
int iSizeOfArray(int* &piArray) { 
    piArray = new int[iNumberOfElements]; 
    ... 
    return iNumberOfElements; 
} 

を使用しているため、そのサイズを返すための機能を提供するために、このようなコードを使用しなければなりませんでした、ポインタは参照渡し(またはダブルポインタを使用)する必要があります。それはメモリリークが生じる値によって渡される場合、そうでない場合、メモリポインタのローカルコピーに割り当てられます。あなたは、ポインタのSTLのコレクションを持っているし、STLのアルゴリズムを使用して にそれらを変更したい場合は

0

あなたがこれを必要とするかもしれ別の状況です。 C++ 98のfor_eachの例あなたはたChangeObject(オブジェクト*項目)署名を使用する場合

struct Storage { 
    typedef std::list<Object*> ObjectList; 
    ObjectList objects; 

    void change() { 
    typedef void (*ChangeFunctionType)(Object*&); 
    std::for_each<ObjectList::iterator, ChangeFunctionType> 
       (objects.begin(), objects.end(), &Storage::changeObject); 
    } 

    static void changeObject(Object*& item) { 
    delete item; 
    item = 0; 
    if (someCondition) item = new Object(); 
    } 

}; 

そうしないと、ポインタのコピーではなく、オリジナルのものを持っています。

14

Davidの答えが正しいですが、それはまだ少し抽象的だ場合は、ここでは二つの例は次のとおりです。

  1. あなたは、以前のメモリの問題をキャッチするために、すべて解放されたポインタをゼロにする場合があります。あなたがしたいCスタイル:C++で

    void freeAndZero(void** ptr) 
    { 
        free(*ptr); 
        *ptr = 0; 
    } 
    
    void* ptr = malloc(...); 
    
    ... 
    
    freeAndZero(&ptr); 
    

    を同じことを行うために、あなたが行う可能性があります:リンクされたリストを扱う

    template<class T> void freeAndZero(T* &ptr) 
    { 
        delete ptr; 
        ptr = 0; 
    } 
    
    int* ptr = new int; 
    
    ... 
    
    freeAndZero(ptr); 
    
  2. - 多くの場合、単純に次のノードへのポインタとして表現:結果はもうNULLポインタではありませんので、この場合は

    struct Node 
    { 
        value_t value; 
        Node* next; 
    }; 
    

    、あなたは空のリストに挿入したとき、あなたは必ず入ってくるのポインタを変更する必要があります。これは、関数から外部のポインタを変更する場合であるので、その署名にポインタへの参照を持っているでしょう:

    void insert(Node* &list) 
    { 
        ... 
        if(!list) list = new Node(...); 
        ... 
    } 
    

例はthis questionにあります。 C++プログラマの

50

50%が、削除後にnullに自分のポインタを設定したい:

template<typename T>  
void moronic_delete(T*& p) 
{ 
    delete p; 
    p = nullptr; 
} 

参照することなく、あなただけの、発信者に影響を与えない、ポインタのローカルコピーを変更することになります。あなたはパーサ関数を記述し、機能が正しくパーサによって認識された最後の文字の後ろに前方にそのポインタをプッシュすることになっている場合は、それを読み取り元のソースポインタを渡すとき

+15

私は名前が好きです。 ) – 4pie0

+2

この例では、わかりやすく説明しています。 –

+0

私は答えを理解するために愚かな言い回しをするでしょう:それはどうしてmoronic deleteと呼ばれますか?私は何が欠けていますか? – Sammaron

0

一例です。ポインタへの参照を使用すると、関数が元のポインタを移動してその位置を更新することが明確になります。

一般に、関数へのポインタを渡したい場合は、オリジナルのポインタを、元のものに影響を与えずにコピーを移動するのではなく、他の位置に移動させます。

+0

なぜdownvote?私が書いたものに何か問題がありますか?説明するケア? :P – BarbaraKwarc

関連する問題