(タイプ&名前)、および(タイプ*名)などのパラメータ定義の違いは何ですか?

StackOverflow https://stackoverflow.com/questions/948947

  •  09-09-2019
  •  | 
  •  

質問

非常に基本的な質問には、まだ、そこにC ++達人から聞いていいでしょう。

C ++におけるによって参照パラメータを宣言するための2つのかなり類似した方法があります。

1) "アスタリスク" を使用

void DoOne(std::wstring* iData);

2)の使用 "アンパサンド" ます:

void DoTwo(std::wstring& iData);

各メソッドの意味は何ですか? どんな落とし穴年代には、どのような場合にはありますか?

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

ボーナス#2:のstd :: wstringのは、意図的に使用されています。それぞれの場合に、標準ライブラリクラスへの含意は何でしょうか?

役に立ちましたか?

解決

#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:NULL関数の文脈における関数パラメータの有効な値であれば、ポインタとして渡し、それ以外の場合は参照として渡す

理由、それは(いけない!)今まで、その後NULLのチェックの手間を介して自分自身を入れないで、NULLできない場合ます。

例を書いている間、

、私は自分の答えを思い付きました。下記以外の何か?

それらのそれぞれの結果は非常に似ている:メモリ内のオブジェクトへの参照は、メソッドの範囲内で終わります。それらのいずれかのための厳格なメモリ要件はないように思われます。オブジェクトは、スタックまたはヒープのいずれかであることができます。

スタックの場合の各方法は、このように呼ばれるであろう:

{
    std::wstring data;
    DoOne(&data);
    DoTwo(data);
}
それはヒープに来るとき、

しかし、第二のアプローチは、オブジェクトがメソッドを呼び出す前に存在しなければならないことを必要とするであろう。オブジェクトが存在しない場合は、呼び出し側は例外ではなく、呼び出し先を起こすます。

{
    std::wstring* pData = new std::wstring();
    DoOne(pData);
    DoTwo(*pData);
}
メモリ不足の状態が発生し、pDataをNULLを終わる場合は、

上記では、クラッシュがDoTwo前に起こるだろうが、ドゥーンはNULLを飲み込むだろうし、後でいくつかの時間をクラッシュする可能性があります。

私はC ++グレ(私の履歴書上は除く)自分自身を呼び出すwouldntのが、私は言うだろう。 (関数はnullをチェックしたいすなわち)ポインタとしてパラメータを渡すのいずれかの使用をtheresのない限り、常に参照を使用します。

また、オブジェクトを返す関数のために行くこと、ポインタを返すことは何とかそれがヌルかもしれないと、クラスのユーザーを語っている。

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

のようなもの。

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

{
    std::wstring* pData = new std::wstring();
    DoOne(pData);
    pData->someFunction(); //Crash
}

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

  

それらのそれぞれの結果はかなりあります   同様の:でオブジェクトへの参照   メモリは、メソッドの中に終わります   範囲。厳密なはないように思われます   それらのいずれかのメモリ要件ます。

connsiderます:

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

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

とは対照的
void f( int & r ) }
   int * p = & r;
}

ここでRは、自分自身の存在を持っていない、それは単に参照です。私はそのを取るWhem アドレス私は、rが参照するもののアドレスを取っています。

NULLポインタについてのあなたの発言も間違っています。 NULLポインタをDerefrencingすると、未定義の動作が発生 - これはやクラッシュが発生しない場合があります。

あなたはポインタで変数を取得する関数を記述する場合は、

、あなたはおそらく、ポインタが他のあなたがプログラムのクラッシュを危険にさらす、(例えばないNULL)が有効であるかどうかを確認する必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top