7

文字列一致アルゴリズムの結果を格納するためのベースとして構築しているこの単純なクラスを見てください。

/** Match of a single pattern in full to a single text. */
class Match {
    uint Tpos;

    this(in uint Tpos) { this.Tpos = Tpos; }

    override string toString() {
        return text("Match: Text@",Tpos);
    }
}

ここで奇妙なことが起こります:

auto m1 = new Match(1), m2 = new Match(1);
writeln(m1.toHash());
writeln(m2.toHash());
writeln(m1 == m2);

版画

4464528
4464512
false

これら 2 つのオブジェクトがデフォルトで等しいと見なされるべきではない理由はわかりません。カスタムtoHash()opEquals()関数を記述できると思いますが、それはやり過ぎのようです。Andrei Alexandrescu の D プログラミング言語に関する本 (すばらしい本です!) による、「デフォルトでは、ハッシュはオブジェクトのビット単位の表現を使用して計算されます。」そこに何かアイデアはありますか?

4

3 に答える 3

8

アドレスに依存するtoHashため、独自に実装する必要があります。Object.toHash私の記憶が正しければ、それはただのreturn cast(hash_t)cast(void*)this.

編集:はい、正しく覚えています: https://github.com/D-Programming-Language/druntime/blob/master/src/object_.d#L88

于 2012-08-23T19:26:20.760 に答える
8

ソース コード (dmd2/src/druntime/src/object_.d) から:

class Object
{
/* snip */
    /**
     * Compute hash function for Object.
     */
    hash_t toHash() @trusted nothrow
    {   
        // BUG: this prevents a compacting GC from working, needs to be fixed
        return cast(hash_t)cast(void*)this;
    }
/* snip */
    /**
     * Returns !=0 if this object does have the same contents as obj.
     */
    equals_t opEquals(Object o)
    {
        return this is o;
    }
}

答えは単純に、コードの書き方です。コンテンツ チェックではなく、身元チェックを行います。なぜこのようになっているのですか?よくわかりませんが、最初に書くのは簡単で、十分に機能するので、誰もわざわざ戻って変更することはなかったと思います。

ニュースグループでは、Object からこれらの関数を完全に削除するという議論がありました。そのため、クラスで == が必要な場合は、何かを実装する必要があります。しかし、このようなことになると、ニュースグループでの会話が行動に移すまでにかかる時間は通常かなり長いです。そして、彼らは考えを変えるかもしれません。

現在および近い将来にクラスの等価性を使用する最善の方法は、クラスに独自の opEquals メソッドを記述することです。

于 2012-08-23T19:29:43.070 に答える
4

答えは簡単です。デフォルトではopEquals、オブジェクトの場合、オブジェクトのアドレスを比較します。値のセマンティクスが必要な場合は、オーバーライドする必要があります(または単にを使用しますstruct

補足:の使用inは正しくありません。whereinは、 「このパラメーターをスタックフレームの外にエスケープしない」という意味です(これは、クラスフィールドに割り当てることで行います)。残念ながら、コンパイラはまだこれを強制していません。そのため、エラーは発生しませんでした。scope constscope

于 2012-08-23T19:25:22.380 に答える