2009-06-30 1 views
5

私はC++に比較的新しい(約1年間の経験、オンとオフ)。私はポインタを定義するための構文としてtype * nameの決定を導いたのは不思議です。変数のメモリアドレスを参照するコードでは、&シンボルが他のどこでも使用されているため、構文はtype & nameである必要があります。だから、intポインタの伝統的な例を使用しますポインタを定義するときに "type&var"の代わりに "type * var"を使用するのはなぜですか?

int a = 1; 
int * b = &a; 

は私がちょうど見ていないよ、このためのいくつかの理由があります確信している、と私は大好きです

int a = 1; 
int & b = &a 

なりますC++のベテランの意見を聞いてください。

おかげで、 -S

+2

"C/C++"とは言わないでください。 CとC++は異なる言語です。 –

+0

それを変更しましたが、ポインタは両方で同じように動作しませんか? – spencewah

+0

Cには参照がありません。 –

答えて

7

C++はCの構文を採用しています。 "The Development of the C Language"(Dennis Ritchie)のように、Cは型の構文が使用に従うべきであると判断されたので、型宣言のポインタに*を使用します。 [化合物型]の各オブジェクトについて

、基礎となるオブジェクトに言及する方法が既に存在した:インデックス配列は、ポインタの[*]間接演算子を使用し、関数を呼び出します。類推的推論は、名前が典型的に現れる表現構文の名前を反映する名前の宣言構文につながった。したがって、

int i, *pi, **ppi; 

整数、整数へのポインタ、整数へのポインタへのポインタを宣言します。これらの宣言の構文は、式でi、* pi、および** ppiがすべてint型を生成するという観察結果を反映しています。ここで

は、より複雑な例です:

int *(*foo)[4][]; 

この宣言は、表現*(*foo)[4][0]int型を持つ意味、そしてそのから(と[]が単項*よりも優先順位が高いことを)あなたはタイプをデコードすることができます。 fooは、intへのポインタの配列のサイズ4の配列へのポインタです。

この構文は、Cとの互換性のためにC++で採用されました。また、C++には宣言で&が使用されています。

int & b = a; 

上記ライン型intの別の変数への参照変数の参照元を意味します。参照とポインタの違いは、参照は初期化されたものに過ぎず、参照先が変更されず、自動的に参照解除されるということです。

int x = 5, y = 10; 
int& r = x; 

int sum = r + y; // you do not need to say '*r' automatically dereferenced. 

r = y; // WRONG, 'r' can only have one thing pointing at during its life, only at its infancy ;) 
+0

ありがとうございました。私は、参照とポインタについて誤った仮定をしていました(主に、同じでない場合には同じものです)。 – spencewah

1

あなたの第二の例は、有効なCコードのみC++コードではありません。違いは、一方がポインタであり、他方が参照であることです。

右側では、 '&'は常にアドレス-nを意味します。定義では、変数が参照であることを示します。

右側では、「*」は常にアドレスの値を意味します。定義では、変数がポインタであることを示します。

参考文献とポインタは同じですが、同じではありません。このarticleは違いを扱います。

+0

2番目のブロックが法的コードであるとは思われません - これは仮説的な例です。 –

+0

ありがとうございました。記事(参考文献と参考文献の曖昧さ回避)が役立っています。 – spencewah

+0

2番目の例は、CでもC++でも有効ではありません。値への参照をバインドするためにアドレス演算子を使用しません。 –

1

代わりとしてint* bを読んで "B intへのポインタである"、int *bとしてそれを読む: "* bはintです"。次に、あなたは&を抗*として持っています:* bはintです。 *bのアドレスは&*b、またはbです。

-2

私は答えが "それはK & Rのやり方だから"と思うかもしれないと思います。

Downvoting fools。なぜ私が間違っているのか説明してください。

K & Rは、ポインタを宣言するためのCの構文が何であるかを決定した人です。

これはintではありません& x; int * xの代わりに。なぜならそれは言語がそれを作った男たちによって定義された方法です - K & R.

3

あなたは視覚的な思想家であれば、それはデータ値に通じるブラックホールとしてアスタリスクを想像するのを助けることができます。したがって、それはポインタです。

アンパサンド穴の反対側の端部であり、解明さアスタリスク又はパイロットがブラックホールから出る遷移を乗り越えるように不規則過程で約ウォブリング宇宙船と考えます。

私は、C++がアンパサンドの意味をオーバーロードして、私たちに参照を与えることが非常に混乱していることを覚えています。 Cを使用している国際的な聴衆によって正当化され、キーボードの制限に関する既知の問題を抱えていた、それ以上の文字の使用を避けようとする絶望的な試みで、彼らは混乱の主な原因を追加しました。

C++の助けになることの1つは、参考文献としてのあらかじめ用意されている逆参照ポインタと考えることです。引数を渡すときに& someVariableを使用するのではなく、someVariableを定義したときに末尾のアンパサンドをすでに使用しています。それからもう一度、あなたをさらに混乱させるかもしれません!

私のペットの一つは、私はAppleのObjective-Cのサンプルに公布見に不幸だった、嫌い、代わりにint* someIntPointer

IMHOのレイアウトスタイルint *someIntPointerで、変数にアスタリスクを維持することは、昔ながらのCであります変数をどのように定義するかの仕組みをデータ型に基づいて強調しています。

someIntPointerのデータ型は、文字通り整数へのポインタであり、宣言にはそれを反映する必要があります。人が同じライン上で混在ポインタと値を宣言する機能は、意図的に、強力であると主張する一方で

int* a, b; // b is a straight int, was that our intention? 

int *a, *b; // old-style C declaring two pointers 

int* a; 
int* b; // b is another pointer to an int 

:これは、次のような微妙なバグを避けるために、あなたは1行に1つの変数を宣言する必要性につながるん私はそれが微妙なバグと混乱につながるのを見ました。

+0

+1、宣言構文についての素晴らしいコメント。 –

4

私はデニス・リッチーがThe Development of the C Languageでこれを答えたと思います。そのような構成 タイプの各オブジェクトについて

、 への道は、基礎となるオブジェクトを言及すでにありました:インデックス 配列、コール関数では、ポインターに対して 間接演算子を使用します。 類推の結果、 の名前の宣言構文は、 の名前が通常表示される式構文の名前の の名前に反映されました。したがって、

int i, *pi, **ppi; 

は整数、 整数へのポインタ、 整数へのポインタへのポインタを宣言する。これらの 宣言の構文は、式で使用された場合、 のi、* pi、および** ppiのすべてが int型の結果を示しています。 同様に、

int f(), *f(), (*f)(); 

は整数、整数に ポインタを返す関数、整数を返す 関数へのポインタを返す関数を宣言。

int *api[10], (*pai)[10]; 

は整数へのポインタの配列、及び 整数の配列へのポインタを宣言する。これらのすべてのケースでは、 の変数の宣言は、 という型の式で使用され、 の型は 宣言の先頭に名前が付けられています。

したがって、type * varを使用すると、宣言でポインタの使用法(逆参照)を反映できるため、ポインタを宣言できます。この記事で

、リッチーもint array[10]とは対照的に「NB」、「B」プログラミング言語の拡張版で、彼はintの配列を宣言し、intへのポインタを宣言するint pointer[]を使用したことを詳述します。

+0

確かに。そしてint i、&i;私はintを返さないので、それは違法だろう。だからこそ、Cでは&iを使用していないので、C++では&iを使用していません。悲しいことに、C++はこの対称性を破ってintを生成しました&a = i;有効なコードでも、 "&i"はintを生成しません。 –