web-dev-qa-db-ja.com

ポインタのユースケースと利点は何ですか?

ポインターの利点を理解するのに苦労します(低レベルのプログラミングを除く)。

Stringやchar []の代わりにchar *を使用する理由、またはポインター演算がもたらす利点.

では、ポインタの利点と使用例は何ですか?

10
OliverS

動的メモリの場所、多くのデータ構造、および大量のデータの効率的な処理には、ポインタが必要です。ポインターがないと、すべてのプログラムデータをグローバルに割り当てるか、関数または同等のものに割り当てる必要があり、データの量が当初許可していた量を超えた場合、頼りになりません。ここでは絶対を使用することをためらっていますが、私の知る限り、すべての現代のコンピューター言語には何らかの形でポインターがあります。

ポインタを使用するほとんどの言語では、ポインタである特定の種類の参照があり、おそらくそうでない特定の種類の参照があり、さらに表記上の違いはありません。 LISP consセルはポインターのペアですが、fixnumはポインターではありません。 Javaでは、クラスのインスタンスに使用される変数はポインターですが、intはポインターではありません。言語構文はそれを反映していません。

Cは、ポインターがオプションで明示的であり、明示的なポインター演算を許可するという点で異常です。 _struct foo bar; struct foo * baz;_を記述することは完全に可能であり、bazにメモリを割り当てたら、barbazの両方を使用して_struct foo_ sを表すことができます。ポインタはオプションなので、表記上の違いがあると便利です。 (_boost::shared_ptr<foo> bar;_、bar.reset()には1つの意味があり、bar->reset()には多くの異なる意味がある可能性があるため、C++ではスマートポインターに不可欠です。)

(実際には、Pascalの_^_など、Cが最初に開発されたときに明示的なポインターが他の言語でよく使用されていました。Cは、現在最も一般的に使用されている言語よりも古い言語であり、表示されています。)

Cの設計目標の1つは、Unixを書き込むことでした。そのため、メモリの場所を詳細に処理する必要がありました。 (実際には、Cは設計時に一般的なシステム実装言語のファミリーの1つであり、もう1つの例は制御データコンピューター用のCybolです。Cは大ヒットしたものです。)したがって、Cポインターを直接操作できます。メモリアドレスの割り当てと新しいアドレスの計算。これはまた、Cでいくつかの設計上の決定につながりました。C配列はポインター演算に大きく基づいており、実際、配列は非常に多くの状況でポインターに減衰します。参照によるC関数への変数の受け渡しは、ポインターによって行われます。配列や、他の現代の言語のような形式で参照によって変数を渡す必要はなかったため、Cはそれらを取得しませんでした。

つまり、今日のほとんどの言語では、事実を気にせずに常にポインタを使用しているのです。 Cでは、そしてC++ではそれほどではありませんが、ポインタを使用して低レベルの処理を行うか、または特別な表記法がない高レベルの処理を実行します。

6
David Thornley

複雑なデータ構造。リンクされたリストやバイナリツリーのようなものは、ポインタなしでは構築できません。

ポインタの「長所」と「短所」はありません。それらはハンマーのような単なる道具です。

10
zvrba
  • ポインタを使用すると、実行時にメモリを割り当てたり割り当て解除したりできます。
  • また、コピーすることなく、許可された範囲外の大きなデータ構造を使用できます。

C++、Javaおよびその他の同じタイプの言語での参照は、単なる「安全なポインタ」です。これらの参照は、Javaでよく使用されます。

2
Gulshan

ほとんどすべてのコンピュータプログラムは、メモリ内の値を調べて変更する必要があります(十分に古い私たちにとっては、「ピーク」と「ポーキング」と呼ばれます)。これらの値がメモリ内のどこにあるかを制御して、結果を予測できるようにする必要があります(場合によっては、順序が重要です。実行可能コードのロードは1つの例です)。したがって、メモリ内の場所を表すデータ型が必要です。あなたのプログラミング環境が抽象化の下でそれを隠したとしても、それはまだそこにあります。

2
user4051

char*は、ポインタの扱いにくい例です。おそらく、std::stringよりもchar*(または、Unicode/ansi /マルチバイトの特殊性を処理するより優れた型)を使用する方が良いでしょう。他のほとんどすべてのポインタの例(Employee*PurchaseOrder*、...)には、多くの利点があります。

  • 単一の関数よりも大きなスコープ-オブジェクトをヒープ上に割り当て、ポインタを長時間渡す
  • 値渡しのコピーコストがないため、ラージオブジェクトの関数呼び出しが高速
  • 関数に渡されたパラメーターを変更できるようにする1つの方法
  • オブジェクト全体ではなくアドレスのみをコピーするコレクションでスペースと時間を節約する

実際、ポインタは非常に重要なので、ポインタがないように見えるほとんどの言語には実際にはポインタしかありません。 C#とJavaの参照型は、基本的には固体オブジェクトに偽装されたポインターです。

現在、ポインター操作(p++ポインター、またはp += delta)はまったく別の話です。危険だと思う人もいれば、すばらしいと思う人もいます。しかし、それはあなたの質問からさらに遠いです。

2
Kate Gregory

ポインターは、データ構造とプログラム実行フットプリントを低く保つことの両方で、より高速になり、オーバーヘッドが少なくなります。 (「できる」という言葉に注意してください。)

一般的には、独自の割り当てを実行するか、自分に代わって何かを実行させることによってリソースを割り当てた場合のルールは、完了時にリソースを解放することです。

上記を実行する負担は、ランタイムに実行させるのではなく、責任を開発者に戻すことです。これには、物が長持ちしたり、境界を越えたり、より適切なタイミングで廃棄されたり、ガベージコレクターの重さを運ぶ必要がないという点で、いくつかの利点があります。

通常は例外とスコープが関係するエキゾチックなケースでは、クリーンアップを行うコードを回避する場合、もう少し注意する必要があるEdgeケースがあります。現実的には、これらのケースは設計することができます。私たちは何十年もの間、マネージコードなしで生活していました。

多くの場合、ポインターを「ハード」にするのは、ハードウェアレベルで何が行われているのかを理解していないだけです。それは間接的なものに過ぎません。

ポインターは、より多くの生のアクセスを提供し、これは非常に役立つ、賢い、または必要な場合があります。どこを指しても、ほとんど何でも扱うことができます。あなたが神のような力を善のために使うなら、それはとても、とても良いことです。

反対側は通常、何かを解放するのを忘れたり、複数回解放したり、解放された後に何かを参照したり、どこにも指していないときに何かを参照したりすることによって無駄になります。これらのことはしばしば見事なクラッシュを引き起こします、そして正直に言うと、通常、ポインタが壊れやすいというより、論理的な問題があることを示しています。

あなたが堅実な開発者であれば、ポインタを使用することは他のどのデータ構造よりも問題になりません。繰り返しになりますが、それはロケット科学ではありません。人々は何十年もの間、まばたきさえせずにそれを行いました。最近はあまり詳しく教えられていません。

そうは言っても、ポインタが必要でない限り、優れたガベージコレクションが提供する納得のいくエキゾチックなケースによって、管理された環境での作業がより快適になります。一部のメモリを取得して使用し、破棄することができるのは素晴らしいことです。そうすることが理にかなっている場合、後で破棄される可能性があることを知っています。これは、余分な処理を行うランタイムと引き換えに、コーダー側のコードが少し少なくなります。

1

最良の答えは実際に質問に含まれています:ポインターは低レベルのプログラミング用です。確かに、Cを使用している場合、ポインターを使用しないことは、片手を後ろで縛ったプログラミングのようなものですが、その答えは、代わりに高水準言語を使用することです。

0
Larry Coleman