Go 言語では、スライスがメモリ内の別の場所に移動されると、要素へのポインタが変わります。スライスは動的配列であるため、その基礎となるデータ構造には、配列要素へのポインタと、スライスの長さと容量の情報が含まれています。スライスが再割り当てまたは拡張されると、スライスが元々指していた要素ポインタは無効になります。したがって、スライスの移動後も以前のポインターが使用されている場合、間違ったメモリ位置にアクセスしたり、他の例外がスローされたりする可能性があります。これを回避するには、スライスの移動後に要素へのポインタを再取得して、ポインタの有効性と正確性を確認する必要があります。ポインタを再取得することで、スライスを移動した後もスライス内の要素を正しく操作し、アクセスし続けることができます。
次のコードがあります
リーリーまず、1 int のスライスを作成します。その len は 1 で、cap も 1 です。次に、その最初の要素へのポインターを取得し、印刷で基になるポインター値を取得します。予想通り、問題なく動作します。
次に、スライスに 3 つの要素を追加して、スライスの容量を拡張し、スライスをメモリ内の別の場所にコピーしました。その後、(ポインターを取得して) スライスの最初の要素のアドレスを出力します。これは、b
に格納されているアドレスとは異なります。
しかし、b
の基礎となる値を出力すると、これも正常に動作します。なぜ機能するのかわかりません。私の知る限り、最初の要素 b
が指すスライスはメモリ内の別の場所にコピーされているため、その前のメモリは解放されているはずです。ただし、まだ存在しているようです。
マップを見ると、まったく同じ問題のため、golang ではキーによって要素にポインターを作成することさえできません。基になるデータがメモリ内の別の場所に移動される可能性があります。ただし、スライスには非常に適しています。なぜそうなるのでしょうか?正確にはどのように機能するのでしょうか?メモリを指す変数がまだあるためにメモリが解放されないのでしょうか?地図とどう違うの?
Go がスライスをメモリ内の別の場所に移動すると、要素へのポインタはどうなりますか?
何もありません。
[W]b
の基礎となる値を出力すると、これも正常に動作します。なぜ機能するのかわかりません。
なぜうまくいかないのですか?
元々指されていたメモリの場所はまだ存在しており、変更されていません。何か (例: b
) がそれを参照している限り、それは引き続き使用可能です。そのメモリへのすべての参照が削除されると (つまり、範囲外になると)、ガベージ コレクターは、そのメモリが他のものによって使用されることを許可する可能性があります。
以上がGo がスライスをメモリ内の別の場所に移動すると、要素へのポインタはどうなりますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。