どのような状況で、C++でこの種のコードを使用しますか?
void foo(type *&in) {...}
void fii() {
type *choochoo;
...
foo(choochoo);
}
ポインターが指しているオブジェクトではなく、ポインターを変更する必要がある場合は、参照によってポインターを渡します。
これは、ダブルポインターが使用される理由に似ています。ポインターへの参照を使用する方が、ポインターを使用するよりも若干安全です。
C++プログラマの50%は、削除後にポインターをnullに設定することを好みます。
template<typename T>
void moronic_delete(T*& p)
{
delete p;
p = nullptr;
}
参照がなければ、ポインタのローカルコピーを変更するだけで、呼び出し元には影響しません。
デビッドの答えは正しいですが、それでもまだ少し抽象的な場合は、2つの例を示します。
メモリの問題を早期に発見するために、すべての解放されたポインターをゼロにすることができます。行うCスタイル:
void freeAndZero(void** ptr)
{
free(*ptr);
*ptr = 0;
}
void* ptr = malloc(...);
...
freeAndZero(&ptr);
同じことをするC++では、次のようにすることができます。
template<class T> void freeAndZero(T* &ptr)
{
delete ptr;
ptr = 0;
}
int* ptr = new int;
...
freeAndZero(ptr);
リンクリストを扱う場合-多くの場合、次のノードへのポインタとして単に表されます:
struct Node
{
value_t value;
Node* next;
};
この場合、空のリストに挿入するときは、結果がNULL
ポインターではなくなるため、着信ポインターを必ず変更する必要があります。これは、関数から外部ポインターを変更する場合です。そのため、署名にポインターへの参照が含まれます。
void insert(Node* &list)
{
...
if(!list) list = new Node(...);
...
}
this question に例があります。
私の会社はSTLを使用して「オブジェクト」であるため、渡されたポインターにメモリを割り当ててサイズを返す関数を提供するには、このようなコードを使用する必要がありました。
int iSizeOfArray(int* &piArray) {
piArray = new int[iNumberOfElements];
...
return iNumberOfElements;
}
ナイスではありませんが、ポインタは参照渡しする必要があります(またはダブルポインタを使用します)。そうでない場合、メモリリークが発生する値で渡される場合、メモリはポインタのローカルコピーに割り当てられます。
一例は、パーサーが正しく認識した最後の文字の後ろにそのポインターを前方にプッシュすることになっている場合に、パーサー関数を作成して読み取り元のソースポインターを渡す場合です。ポインターへの参照を使用すると、関数が元のポインターを移動してその位置を更新することが明確になります。
一般に、関数へのポインターを渡し、元に影響を与えずにそのコピーを移動するのではなく、originalポインターを他の位置に移動させたい場合は、ポインターへの参照を使用します。
これが必要になる可能性がある別の状況は、ポインタのstlコレクションがあり、stlアルゴリズムを使用してそれらを変更する場合です。 C++ 98のfor_eachの例。
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();
}
};
それ以外の場合、使用する場合 changeObject(Object * item) 署名にはポインタのコピーがあり、元のコピーではありません。