6

私は最近、非常に興味深いと思った以下のリンクに出くわしました。

http://en.wikipedia.org/wiki/XOR_linked_list

  • 汎用デバッグツールはXORチェーンをたどることができないため、デバッグがより困難になります。[1]
  • メモリ使用量の減少の代償は、コードの複雑さの増加であり、メンテナンスがより高価になります。
  • ほとんどのガベージコレクションスキームは、リテラルポインタを含まないデータ構造では機能しません。
  • ポインターのXORは、一部のコンテキスト(C言語など)では定義されていませんが、多くの言語では、ポインターと整数の間で何らかの型変換が提供されています。
  • リストをトラバースしていない場合、たとえば、リストアイテムへのポインタが別のデータ構造に含まれている場合、ポインタは読み取り不能になります。
  • リストをトラバースしている間、次のノードのアドレスを計算するために、以前にアクセスしたノードのアドレスを覚えておく必要があります。

今、それが低水準言語専用なのか、それともC#内でも可能なのか疑問に思っています。

C#で同じ結果を生成するための同様のオプションはありますか?

4

7 に答える 7

8

TL; DR C#で概念実証XorLinkedList実装をすばやく作成しました。

これは、C#で安全でないコードを使用して絶対に可能です。ただし、いくつかの制限があります。

  1. XorLinkedListは「管理されていない構造体」である必要があります。つまり、管理された参照を含めることはできません。
  2. C#ジェネリックの制限により、リンクリストをジェネリックにすることはできませんwhere T : struct

後者は、ジェネリックパラメーターをアンマネージ構造体に制限できないためと思われます。where T : struct管理された参照を含む構造体も許可します。

これは、XorLinkedListが保持できるのは、int、ポインター、その他のアンマネージ構造体などのプリミティブ値のみであることを意味します。

C#での低水準プログラミング

private static Node* _ptrXor(Node* a, Node* b)
{
    return (Node*)((ulong)a ^ (ulong)b);//very fragile
}

とても壊れやすいです、私は知っています。C#ポインターとIntPtrはXOR演算子をサポートしていません(おそらく良い考えです)。

private static Node* _allocate(Node* link, int value = 0)
{
    var node = (Node*) Marshal.AllocHGlobal(sizeof (Node));
    node->xorLink = link;
    node->value = value;
    return node;
}

Marshal.FreeHGlobal後でそれらのノードを忘れないでください(完全なIDisposableif(disposing)パターンを実装し、ブロックの外にフリーコールを配置するようにしてください。

private static Node* _insertMiddle(Node* first, Node* second, int value)
{
    var node = _allocate(_ptrXor(first, second), value);
    var prev = _prev(first, second);
    first->xorLink = _ptrXor(prev, node);
    var next = _next(first, second);
    second->xorLink = _ptrXor(node, next);
    return node;
}

結論

個人的には、C#でXorLinkedListを使用することは決してありません(メモリアロケータやカーネルデータ構造などの非常に低レベルのシステムを記述している場合は、Cで使用する可能性があります。他の設定では、ストレージ効率を少し上げるだけでは苦労する価値はありません。 C#の管理対象オブジェクトと一緒に使用できないという事実は、日常のプログラミングにはほとんど役に立たないものにします。

また、ストレージは現在ほとんど無料です。メインメモリもあります。C#を使用している場合は、ストレージについてあまり気にしないでしょう。私はどこかでCLRオブジェクトヘッダーが約40バイトであったことを読んだので、この1つのポインターはあなたの懸念の中で最も少ないでしょう;)

于 2011-05-13T13:40:01.477 に答える
1

C#では通常、そのレベルで参照を操作することはできないため、残念ながらできません。

于 2011-05-12T21:09:47.113 に答える
1

提案されている安全でない解決策の代替として。

リンクリストを配列またはリストコレクションでバックアップした場合、メモリポインタの代わりに「next」および「previous」が配列へのインデックスを示し、安全でない機能を使用せずにこのxorを実装できます。

于 2011-05-12T21:27:28.873 に答える
1

C#でポインターを操作する方法はいくつかありますが、オブジェクトへのポインターは一時的にしか使用できないため、このシナリオでは使用できません。これの主な理由はガベージコレクションです。XORポインターのようなことを実行し、後でそれらをunXORできる限り、GCは特定のオブジェクトを収集しても安全かどうかを知る方法がありません。

1つの大きな配列でインデックスを使用してポインタをエミュレートすることで非常によく似たものを作成できますが、単純な形式のメモリ管理を自分で実装する必要があります(つまり、新しいノードを作成するとき、配列のどこに配置する必要がありますか?)。

もう1つのオプションは、C ++ / CLIを使用することです。これにより、一方ではポインターとGCの完全な柔軟性と、他方では必要なときにフレームワークにアクセスできるようになります。

于 2011-05-12T21:29:11.637 に答える
0

ここで大まかに一般化すると、C#は読みやすさとクリーンなインターフェイスの道を進んだように見えますが、ビットをいじってすべての情報を可能な限り密集させる道ではありません。

したがって、ここで特別なニーズがない限り、提供されているリストを使用する必要があります。将来のメンテナンスプログラマーはそれを感謝します。

于 2011-05-12T21:38:06.403 に答える
0

もちろん。クラスをコーディングするだけです。c#のXOR演算子は^コーディングを開始するために必要なのはこれだけです。これには、コードを「安全ではない」と宣言する必要があることに注意してください。c#でポインタを使用する方法については、ここを参照してください。

于 2011-05-12T21:10:54.290 に答える
-4

ただし、C#がオブジェクトをどのように見るかを理解する必要がある可能性があります。インスタンス変数には、実際にはオブジェクトは含まれていませんが、メモリ内のオブジェクトへのポインタが含まれています。

DateTime dt = DateTime.Now;

dtは、DateTimeスキームを含むメモリ内の構造体へのポインタです。

したがって、フレームワークが通常最も効率的なコレクションをすでに実装しているので、なぜそうするのかはわかりませんが、このタイプのリンクリストを実行できます。思考の呼気としてそれは可能です。

于 2011-05-12T21:20:28.900 に答える