ポインタの利点を理解するのに苦労します(低レベルのプログラミングを除く)。
Stringやchar []の代わりにchar *を使用する理由、またはポインター演算がもたらす利点
では、ポインタの利点と使用例は何ですか?
ポインタの利点を理解するのに苦労します(低レベルのプログラミングを除く)。
Stringやchar []の代わりにchar *を使用する理由、またはポインター演算がもたらす利点
では、ポインタの利点と使用例は何ですか?
回答:
ポインターは、動的なメモリの場所、多くのデータ構造、および大量のデータの効率的な処理に必要です。ポインターがないと、すべてのプログラムデータをグローバルに割り当てるか、関数または同等のものに割り当てる必要があり、データの量が元々許可していた量を超えた場合、頼りになりません。ここでは絶対を使用することをためらっていますが、私の知る限り、すべての現代のコンピューター言語には何らかの形でポインターがあります。
ポインタを使用するほとんどの言語では、ポインタである特定の種類の参照があり、おそらくそうでない特定の種類の参照があり、それ以上の表記上の違いはありません。Lisp cons
セルはポインタのペアですが、a fixnum
はポインタではありません。Javaでは、クラスのインスタンスに使用される変数はポインターですが、そうでint
はありません。言語構文はそれを反映していません。
Cは、ポインターがオプションで明示的であり、明示的なポインター演算を許可するという点で異常です。を書くことは完全に可能struct foo bar; struct foo * baz;
であり、メモリを割り当てbaz
たら、bar
とbaz
を表すことができますstruct foo
。ポインタはオプションなので、表記上の違いがあると便利です。(与えられたようにboost::shared_ptr<foo> bar;
、それbar.reset()
はスマートポインターのためのC ++で不可欠です、1つの意味bar->reset()
があり、大きく異なる可能性があります。)
(実際に^
は、Pascal などのCが最初に開発されたとき、明示的なポインターが他の言語でよく使用されていました。Cは、現在一般的に使用されているほとんどの言語よりも古い言語であり、それが示しています。)
Cの設計目標の1つは、Unixを書き込むことでした。そのため、メモリの場所を詳細に処理する必要がありました。(Cは実際には、設計時に一般的なシステム実装言語のファミリーの1つであり、もう1つの例は制御データコンピューター用のCybolです。Cは大ヒットしたものです。)したがって、Cポインターを直接操作することができます。メモリアドレスの割り当てと新しいアドレスの計算。これはまた、Cでいくつかの設計上の決定につながりました。C配列はポインター演算に大きく基づいており、実際、配列は非常に多くの状況でポインターに減衰します。参照によるC関数への変数の受け渡しは、ポインターによって行われます。配列や、他の現代的な言語のような形式で参照によって変数を渡す必要はなかったため、Cはそれらを取得しませんでした。
ですから、答えは、今日のほとんどの言語では、事実に気付かれることなく常にポインタを使用しているということです。Cでは、C ++ではそれほどではありませんが、ポインターを使用して低レベルの処理を行うか、特別な表記法がない高レベルの処理を実行します。
複雑なデータ構造。リンクされたリストやバイナリツリーのようなものは、ポインタなしでは構築できません。
ポインタの「長所」と「短所」はありません。それらはハンマーのような単なる道具です。
C ++、Java、およびその他の同じタイプの言語での参照は、単なる「安全なポインタ」です。そして、これらの参照はJavaでよく使用されます。
NULL
、作成後に変更することもできません。
ほとんどすべてのコンピュータプログラムは、メモリ内の値を調べて変更する必要があります(十分に古い私たちにとっては、「ピークおよびポーキング」と呼ばれます)。これらの値がメモリ内のどこにあるかを制御して、結果を予測できるようにする必要があります(場合によっては、順序が重要です。実行可能コードのロードは1つの例です)。したがって、メモリ内の場所を表すデータ型が必要です。あなたのプログラミング環境が抽象化の下でそれを隠したとしても、それはまだそこにあります。
char*
ポインタの不器用な例です。おそらく、を使用std::string
するより(または、Unicode / ansi /マルチバイトの特殊性を処理するより優れた型を使用する方が)良いでしょうchar*
。ポインタのほぼすべての他の例えば(Employee*
、PurchaseOrder*
、...)、しかし、多くの利点があります。
実際、ポインタは非常に重要なので、ポインタがないように見えるほとんどの言語には、実際にはポインタしかありません。C#とJavaの参照型は、基本的には固体オブジェクトに偽装されたポインターです。
さて、ポインタ操作(p++
ポインタ上、またはp += delta
)はまったく別の話です。危険だと思う人もいれば、すばらしいと思う人もいます。しかし、それはあなたの質問からさらに遠いです。
ポインタは、データ構造とプログラム実行フットプリントを低く保つことの両方で、より高速になり、オーバーヘッドが少なくなります。(「できる」という言葉に注意してください。)
一般的には、独自の割り当てを実行するか、自分に代わって何かを実行させることによってリソースを割り当てた場合、ルールは、完了時にそれを解放することです。
上記を実行する負担は、ランタイムに実行させるのではなく、責任を開発者に戻すことです。これには、物が長持ちしたり、境界を越えたり、より適切なタイミングで廃棄されたり、ガベージコレクターの重さを運ぶ必要がないという点で、いくつかの利点があります。
エキゾチックなケースでは、通常は例外とスコープが関係しますが、クリーンアップを行うコードを回避する場合、もう少し注意する必要があるいくつかのエッジケースがあります。現実的には、これらのケースは設計することができます。私たちは何十年もの間、マネージコードなしで生活していました。
多くの場合、ポインターを「ハード」にするのは、ハードウェアレベルで何が行われているのかを理解していないだけです。それは間接的なものに過ぎません。
ポインターを使用すると、より多くの生のアクセスが可能になり、これは非常に役立つ、賢い、または必要な場合があります。どこにでもポイントして、ほとんど何でも扱うことができます。神のような力を善に使うなら、それはとても、とても良いことです。
反対側は通常、何かを解放するのを忘れたり、複数回解放したり、解放された後に何かを参照したり、どこにも指していないときに何かを参照したりすることによって無駄になります。これらのことはしばしば見事なクラッシュを引き起こします、そして正直に言うと、通常はポインターが壊れやすいというより、論理的な問題があることを示しています。
あなたが堅実な開発者であれば、ポインタを使用することは他のどのデータ構造よりも問題になりません。繰り返しになりますが、それはロケット科学ではありません。人々は何十年もの間、まばたきさえせずにそれを行いました。最近はあまり詳しく教えられていない。
そうは言っても、ポインタが必要でない限り、優れたガベージコレクションが提供する納得のいくエキゾチックなケースによって、管理された環境での作業がより快適になります。一部のメモリを取得して使用し、破棄することができるのは素晴らしいことです。そうすることが理にかなっている場合、後で破棄される可能性があることを知っています。これは、余分な処理を行うランタイムと引き換えに、コーダー側のコードが少し少なくなります。