3

操作を「元に戻す」標準的な方法は何popFrontですか? これはすべての範囲で機能するとは限りませんが、配列などの場合は、

int[] a = [ 1, 2, 3 ];

そして、 の開始ポインタををa.popFront()指すように調整しましたが、その操作を元に戻して を範囲内に戻すにはどうすればよいでしょうか? 私は知っていますが、それは私が探している操作ではありません。a21std.container.insertFront

私が試してみました

a = a[1..$];
a = a[-1..$];

しかし、2 行目はRangeError. また、配列はスライシングをサポートしていますが、私が探している方法は、非ランダム アクセス範囲とスライシングをサポートしない範囲をサポートする必要があります。たとえa[-1..$]うまくいったとしても、それは私の問題を解決しません。

4

2 に答える 2

4

標準的な方法は、ポップする前に範囲のコピーを保存することです。ポッピングは破壊的な突然変異であり、範囲は自由に要素の割り当てを解除したり、基になるツリーのバランスを取り直したり、以前の要素を無効にしたりできます。

したがって:

MyRange old = current.save;
current.popFront();
if (current.front == magicValue) {
    current = old;
}
于 2013-05-12T01:09:28.157 に答える
3

元に戻さないでくださいpopFrontarr[-1 .. $]配列と同等のことさえできません。古いバージョンが必要な場合は、最初に保存する必要があります。

auto saved = range.save;
range.popFront();
range = saved; // "undo" popFront()

配列はそれ以上の機能も提供しません。範囲 API を使用せずに配列で同じことを行うには、次のようにする必要があります。

auto saved = arr;
arr = arr[1 .. $];
arr = saved;

範囲または配列に対するポップ操作を「元に戻す」唯一の方法は、最初に保存してから古いバージョンを使用することです。範囲 API または配列によって提供されるものは他にありません。それらは独自に状態を保存しません (したがって、前の操作を元に戻す方法を知ることができませんでした)。また、配列スライスでさえ、メモリ内でそれらの前または後にどのデータが存在するかを認識していません (また、前または前にメモリにアクセスしようとしています)。 )をヒットしたときに見たように、配列の後は違法ですRangeError

したがって、任意の数の要素のポップオフを「元に戻す」ことを心配する必要がある場合は、元の範囲を保持して、要素の数を追跡するなどのことを行う必要があるでしょう。必要な「元に戻す」レベルの数を引いた数の要素をポップオフできるように、それをポップします。そして、ここで多くのコピーが行われる可能性は低いですが (配列の場合、同じメモリを指しているが、その中の異なる場所にある複数のスライスになるだけです)、スライスを使用して範囲を扱っていない場合は、そのすべてが行われます。特に一度に 1 つのレベルを元に戻そうとしている場合、ポップオフはコストがかかる可能性があります (各要素がポップオフされる前から範囲の保存されたバージョンを保持する可能性があるため)。やろうとしている、

于 2013-05-12T05:48:41.587 に答える