3

他の方法で割り当てられたものへのポインターは、C++ でかなり安全ですか?

ここまでは、すべての動的メモリのニーズに対して STL コンテナー (場合によっては配列ですが、それは別の質問です) を使用してきたため、newキーワードを明示的に使用する必要はありませんでした。int *fooまた、物事を参照するために単純な型ポインターを気軽に使用してきました。今、私はスマート ポインターについて読んでいます (私は Java で歯を磨いたので、これまでこれについて心配する必要はありませんでした)。

それで、私はどれだけ困っていますか?ポインターが指すものが他の破壊条件を持っている限り、裸のポインターを安全に使用し続けることはできますか? それは私が逃げることができるものですが、将来は避けるべきですか? それとも、急いで修正する必要があるのは、進行中の災害ですか?

4

5 に答える 5

6

むき出しのポインターはそれ自体安全です。危険なのは、それらを誤って使用することです (そして、簡単に夢中になる可能性があります)。スマート ポインターは便利ですが、一部の ( shared_ptr) は参照カウントを伴うため、パフォーマンスが低下します。該当する場合はスマート ポインターを使用するようにしてください。ただし、ポインターを使用することは恐ろしい間違いとは見なされません。

STL コンテナーのメンバーを参照するときは、再配置中にアドレスが変更されて奇妙なバグが発生する可能性があるため、注意が必要です。

于 2012-05-14T19:28:06.093 に答える
1

コードを書く人、コードを維持する人がミスを犯さない完璧な世界では、生のポインターは驚くべきものです。

残念ながら、そうではありません。まず第一に、生のポインターはエラーが発生しやすく、ポインターが知らないうちに無効化される可能性のあるメモリを指し、ポインターはエイリアス化され、ポインターが指す内容が変更される可能性があります。

「愚かさ」を補うために、実際にはスマートポインターが必要です。少なくとも何かが「スマート」でなければなりません:)。

非常に内部で作業している場合を除き、生のポインターを使用する必要はありません。単純に「あまりスマートではない」からです。そうは言っても、あなたが非常に注意深く、コードを書いた後にコードを使用する人が非常に注意を払っている場合 (多くの場合、そうではありません)、先に進んで生のポインターを使用しますが、それ以外はスマートを使用しますオーバーヘッドがほとんどまたはまったく発生しないためです。

unique_ptr<>移動するまでオーバーヘッドはまったくありません。移動する場合、メモリに 1 つの NULL が書き込まれます。最新のコンパイラでは、これは頻繁に最適化されています。

shared_ptr<>参照をカウントし、特にマルチスレッド アプリで使用すると、かなりの量のオーバーヘッドが発生する可能性がありますが、これは回避できるため、それほど大きな問題ではありません。

全体として、未加工のポインターを緊急に修正する必要はありませんが、それらの使用はお勧めできません。

于 2012-05-14T19:27:52.987 に答える
1

「ベアポインタは悪い。使用しないでください」という小さな補遺を付けて言うのは完全に正確です。

オブジェクトがあり、それを破棄するのが他の誰かの責任である場合、生のポインターはまったく問題ありません。ただし、クリーンアップ関数を使用してオブジェクトを破棄する必要がある場合は、常にスマート ポインターを使用してください。さらに、クリーンアップしないオブジェクトについては、別のシステム関数ローカル、vectorサイズ変更などによってクリーンアップされる条件に注意してください。

所有権の規則:

  • 所有権なし: T*、いつ使用できなくなるかに注意してください
  • 共有所有権: shared_ptr<T>、必要に応じてカスタム デリーターを使用
  • 固有の所有権: unique_ptr<T, Del>、必要に応じてカスタムの削除機能

常にこれらのルールに従ってください。そうすれば、メモリ リーク、二重解放、不正なポインタ アクセス、または同様のメモリ関連のバグが発生することはありません。

于 2012-05-14T19:31:38.733 に答える
0

むき出しのポインターは、トラブルに巻き込まれやすいため、悪いと見なされます。スマート ポインターは、いくつかの問題を自動的に処理するため、エラーが発生しにくくなります。

すべてのコードを完全に制御できる場合 (つまり、プロジェクトの唯一のコーダーである場合)、基本的なメモリ割り当ての法則と習慣 (「メモリを割り当てた人は誰でもそれを取り除く」) に従う限り、ベア ポインターを使用しても問題ありません。別段の記載がある場合を除きます。」) しかし、コードに関して他の人と作業する場合 (つまり、複数のコーダーがいるプロジェクト)、間違いや誤解への扉が開かれます。

スマート ポインターは、誰がオブジェクトを所有しているか (したがって、誰がそのオブジェクトを解放する必要があるか) を管理します。また、そのオブジェクトを使用する最後のコードがそのオブジェクトを必要としなくなった時期を追跡できるため、割り当てられたデータが共有されたときに安全に割り当てを解除できます。

カウントを参照するスマート ポインターは、ヒープからメモリを割り当てるクラスのデータ メンバーに対して、安全な既定のコピー コンストラクターと安全な既定のコピー代入演算子も生成します。コピーしている元のオブジェクトへの参照カウント スマート ポインターを安全に設定できます。元のオブジェクトまたはクローンのいずれかがスコープ外に出て削除された場合、スマート ポインターを介して管理および共有している割り当てられたメモリは残ります。まだそれを指している他のオブジェクト。これは、裸のポインターには当てはまりません。裸のポインターを使用する場合は、コピー代入演算子とコピー コンストラクターを記述して、メモリを割り当てるオブジェクトを複製し、含まれている/所有されている割り当てられたデータのデータ破損を防ぐ必要があります。

于 2012-05-14T19:58:26.480 に答える
-2

ベアポインターが苦手な時も、あまり気にせずにnewdeleteこの動作により、非常に奇妙なエラーが発生する可能性があります。私が提案するのは、ヒープに割り当てられたいくつかのポインターとオブジェクトを操作する必要がある場合、メモリリークチェッカーValgrindを使用して学習することです。

次に、いくつかの簡単なルールがあります。配列をインスタンス化するときは、new []常にそれらを削除する必要がdelete []あり、逆に、単一のオブジェクトをインスタンス化するときnewは常に呼び出しますdelete

これらの関数は相互に動作するように設計されていないため、混合を避けることを忘れないでください。たとえば、次のようnewにしないでください。deletemallocfreenew[]delete[]

int *a = (int*)malloc(10*sizeof(int));
delete a;

でもこれは

int *a = new int[10];
delete[] a;

Tibor が言ったように、ポインターの使用自体は悪くありませんが、いつものように、「大きな力には大きな責任が伴います」:P

于 2012-05-14T19:34:37.013 に答える