2009-06-04 10 views
5

非常に基本的な質問ですが、それでもC++の教祖から聞いてみるとよいでしょう。(type&name)と(type * name)の違いは何ですか?

C++で参照パラメータによって宣言する方法には、2つのやや類似した方法があります。

1) "アスタリスク" の使用: "アンパサンド" を使用して

​​

2):

void DoTwo(std::wstring& iData); 

各メソッドの意味は何ですか? いずれにしても問題がありますか?

ボーナス#1:#1と#2でメソッドを呼び出す正式な方法は何ですか?それらは両方とも「参照による」と呼ばれていますか?

ボーナス#2:std :: wstringは故意に使用されます。それぞれの場合に標準ライブラリクラスにどのような影響がありますか?

+1

リファレンス/ポインタ引数については多くのことが言われています。こちらも見てください:http://stackoverflow.com/questions/57483/difference-between-pointer-variable-and-reference-variable-in-c。 – xtofl

答えて

5

#1はポインタパラメータ( 'ポインタを渡す')を使用し、#2は参照パラメータ( '参照渡し')を使用します。彼らは非常に似ていますが、呼び出し元のコードは、2つのケースで異なりますのでご注意:

std::wstring s; 

DoOne(&s); // pass a pointer to s 
DoTwo(s); // pass s by reference 

一部の人々は、ポインタ渡しする機能も(sの値を変更する場合がありますことを示している規則を使用して、#1を好みますいずれの機能も可能ですが)。参照渡しはNULLを渡すことができないので、他の人(自分自身を含む)は#2を好む。

constポインタまたは参照を渡すときに別の重要な違いがあります。一時変数はconst参照パラメータに渡すことができます。

void ByConstPointer(const std::wstring&); 
void ByConstReference(const std::wstring*); 

void test() 
{ 
    ByConstPointer(&std::wstring(L"Hello")); // error: cannot take address of temporary 
    ByConstReference(std::wstring(L"Hello")); // fine 
} 
+1

+1は一時変数です! –

1

例を書いているうちに、自分の答えを思いついた。下以外のものは?

それぞれの結果は非常に似ています。メモリ内のオブジェクトへの参照は、メソッドのスコープ内で終了します。それらのいずれにも厳しいメモリ要件はないようです。オブジェクトはスタックまたはヒープのいずれかになります。スタックの場合

の各方法は、このように呼ばれます:まだ

{ 
    std::wstring data; 
    DoOne(&data); 
    DoTwo(data); 
} 

、それはヒープに来るとき、第二のアプローチは、オブジェクトがメソッドを呼び出す前に存在しなければならないことを必要とするであろうこと。オブジェクトが存在しない場合、呼び出し元は呼び出し先ではなく例外を発生させます。上記で

{ 
    std::wstring* pData = new std::wstring(); 
    DoOne(pData); 
    DoTwo(*pData); 
} 

メモリ不足の状態が発生し、pDataをNULLを終わる場合、クラッシュがDoTwo前に起こるだろうが、ドゥーンはNULLを飲み込むだろうし、後でいくつかの時間をクラッシュする可能性があります。

+0

+1あまり追加しない:) – ralphtheninja

+0

ありがとうございます!各メソッドを正式にどのように呼び出すか? –

+0

DoOneは参照渡しで、DoTwoはポインタ渡しです。参照はNULLにすることはできません。コンパイラによって参照が強制されます。だからあなたのステートメント "オブジェクトが存在しない場合は、呼び出し元が例外を引き起こす"は間違っています。また、newはNULLを返すことができません。失敗した場合は、例外がスローされます。だからあなたは心配する必要はありません。ほとんどの場合、参照渡しが優先されます。 – rlbond

0

私は自分自身をC++のgureと呼んでいますが(私の履歴書を除いて)、私は言うでしょう。パラメータとしてポインタを渡す(つまり、関数がnullをチェックしたい)場合は、常に参照を使用してください。

これはまた、オブジェクトを返す関数にも向いています。ポインタを返すと、何らかの理由でnullがあるかもしれないことがクラスのユーザーに伝えられます。

0

DoOneでは、iDataにNULLを割り当てることができます。 DoOneを呼び出した後にそれを使用すると、アプリケーションがクラッシュします。

何か

void DoOne(std::wstring* iData) 
{ 
    //Use iData 
    delete iData; 
    iData = NULL; 
} 

などの
{ 
    std::wstring* pData = new std::wstring(); 
    DoOne(pData); 
    pData->someFunction(); //Crash 
} 
+0

ポインタがNULLに割り当てられているためではなく、オブジェクトが削除されたためクラッシュします。 –

0

あなたが言うとき、あなたの答えは完全に間違っている:

それらのそれぞれの結果はかなり 似ていますへの参照 のオブジェクトは、メソッドの スコープ内で終了します。それらのいずれにも厳しい メモリ要件はないようです。

connsider:

void f(int * p1) { 
    int ** p2 = & p1; 
} 

ここP1明確な「メモリ要件」を持っている - それが存在しなければならないと私はそのアドレスを取ることができなければなりません。これと対照的に

void f(int & r) } 
    int * p = & r; 
} 

ここではrはそれ自体の存在はなく、単なる参考値です。私はそれを取る アドレス私はrが参照するもののアドレスを取っています。

NULLポインタに関するご意見も間違いです。 NULLポインタを破棄すると、未定義の動作が発生します。これはクラッシュする可能性があります。

+0

あなたは、C++に "Pass By Pointer"のようなものは存在しないと言っていますか?あなたが正しいとはいえ、私は疑問はポインタや参照をいつ使うべきかということだと思います。 – xtofl

+0

いいえ、私はそれを言っているわけではありません。 –

0

あなたはポインタで変数を取得する関数を記述する場合、あなたはおそらく、ポインタが有効であるかどうかを確認する必要があります(例えばないNULL)そうしないと、プログラムのクラッシュが発生する可能性があります。

+0

"あなたはプログラムのクラッシュを危険にさらします"。 strcpyのような標準関数はnullをチェックしません。彼らは、(無効な値を渡すことによって)クラッシュする危険を冒しているのは彼らの呼び出し元ではなく、それらの呼び出し元であるという見解を持っています。 –

2

この場合のルール番号1:関数のコンテキストでNULLが関数パラメータの有効な値であれば、それをポインタとして渡します。そうでない場合は、参照として渡します。

理論的には、もしそれができないならば、NULLであるべきではないならば、NULLをチェックする手間を省いてください。

関連する問題