私はポインターをよく理解しており、その使い方もよく理解しています。ただし、配列でのポインターの使用法を理解したことがありません。私はそれを行う方法を知っていますが、配列の直接操作よりもこれを使用する理由がわかりません。配列内のポインターを使用してのみ実行できることを知りたいだけです。ありがとう。
2 に答える
検討:
struct Match {
int scores[30];
char names[30][64];
int ages[30];
char description[1024];
};
この構造体の長さは 3184 バイトです。
Match matches[16];
マッチ[0]とマッチ[1]を交換する必要があると判断した場合、2つを交換するには、次の作業を行う必要があります(これが std::swap の実装方法です):
Match temp; // prepare 3184 bytes on the stack.
temp = matches[0]; // copy 3184 bytes
matches[0] = matches[1]; // copy 3184 bytes
matches[1] = temp; // copy 3184 bytes
それは、データのコピー/移動に多くのCPUサイクルです。
ポインターを使用した場合:
Match* matches[16];
for (size_t i = 0; i < 16; ++i) {
mathces[i] = new Match;
}
std::swap がしなければならないのは、2 つのポインターを交換することだけです。
Match* temp = matches[0]; // 4 or 8 bytes
matches[0] = matches[1]; // 4 or 8 bytes
matches[1] = temp; // 4 or 8 bytes
はるかにクリーンで、最適化された場合、これはおそらくレジスターで実行でき、極端なパフォーマンスが得られます。
これのもう 1 つの利点は、メモリの節約です。4Mb または 8Mb (32/64 ビットに応じて) を占有する 1,000,000 個の Match ポインターの配列を持つことができ、その多くはnullptr
. 現在有用なエントリへのポインタのみが必要です。
1,000,000 個の Match オブジェクトの配列には、3Gb の RAM が必要です。
逆に、1,000,000 個のポインターすべてが一意の Match オブジェクト インスタンスを指す必要がある場合、最大 3Gb のオブジェクトと最大 1Mb のポインターが必要になります。
ご覧のとおり、配列はオブジェクトとは異なります。配列自体がメモリをブロックとして割り当てています。次に、配列には値へのポインターが含まれます。これは、array1 = array2 を実行できることを意味します。値自体はコピーされず、アドレスのみがコピーされます。
配列がポインターである理由は、メモリ管理のためです。配列を複製するのは簡単すぎます。配列はオブジェクトのようには機能しません。
配列のインデックス 1 にアクセスすると、配列に次のように尋ねられます。この配列のインデックス 1 に格納されているアドレスの値を教えてください。
私はC++、特にポインターが得意ではありませんが、これがどのように機能するかはかなり確信しています。