4

私の前の質問に関連)

QT では、QMapドキュメントには次のように記載されています。

QMap のキー タイプは、合計順序operator<()を指定する必要があります。

ただし、 では、ポインターを比較するqmap.hために次のようなものを使用しているようです。std::less

/*
    QMap uses qMapLessThanKey() to compare keys. The default
    implementation uses operator<(). For pointer types,
    qMapLessThanKey() casts the pointers to integers before it
    compares them, because operator<() is undefined on pointers
    that come from different memory blocks. (In practice, this
    is only a problem when running a program such as
    BoundsChecker.)
*/

template <class Key> inline bool qMapLessThanKey(const Key &key1, const Key &key2)
{
    return key1 < key2;
}

template <class Ptr> inline bool qMapLessThanKey(const Ptr *key1, const Ptr *key2)
{
    Q_STATIC_ASSERT(sizeof(quintptr) == sizeof(const Ptr *));
    return quintptr(key1) < quintptr(key2);
}

quintptrポインターをs (の QT バージョンuintptr_t、つまり、ポインターを格納できる unsigned int )にキャストし、結果を比較するだけです。

次の型は、void への任意の有効なポインターをこの型に変換し、その後 void へのポインターに戻すことができるプロパティを持つ符号なし整数型を指定します。結果は元のポインターと等しくなります。uintptr_t

qMapLessThanKey()このon ポインターの実装は問題ないと思いますか?

もちろん、整数型には完全な順序があります。しかし、これは、この操作がポインターの全体的な順序を定義していると結論付けるのに十分ではないと思います。

AFAIKが指定されていないことをp1 == p2意味する場合にのみ、それは真実だと思います。quintptr(p1) == quintptr(p2)

この状態の反例として、ポインターに 40 ビットを使用するターゲットを想像してください。ポインターを に変換しquintptr、最下位 40 ビットをポインター アドレスに設定し、最上位 24 ビットを変更せずに (ランダムに) 残すことができます。これは と ポインター間の変換可能性を尊重するのに十分ですquintptrが、これはポインターの全体的な順序を定義しません。

どう思いますか?

4

2 に答える 2

2

uintptr_t標準では、ポインターを に変換すると、元のポインター型にキャストすると元のポインターが生成される符号なし型の値が生成されることが保証されています。また、任意のポインタを値のシーケンスに分解できることunsigned char、およびそのようなunsigned char値のシーケンスを使用してポインタを構築すると元の値が得られることも義務付けています。ただし、どちらの保証も、実装がポインター型内にパディング ビットを含めることを禁止するものではなく、パディング ビットが一貫した方法で動作することを要求するものでもありません。

コードがポインターの格納を回避し、代わりuintptr_tに から返されたすべてのポインターにキャストしmalloc、後で必要に応じてそれらの値をポインターにキャストし直す場合、結果のuintptr_t値はランキングを形成します。ランキングは、オブジェクトが作成された順序やメモリ内の配置とは何の関係もないかもしれませんが、ランキングにはなります。ただし、ポインターがuintptr_t複数回変換された場合、結果の値は完全に独立してランク付けされる可能性があります。

于 2015-06-04T21:22:14.757 に答える