std::map<T*, U> 的程序是否具有明确定义的行为?

Does a program with std::map<T*, U> have well-defined behaviour?

Comparing pointers to unrelated objects has unspecified results.

这似乎表明该程序可能有未定义的行为,至少因为我们不能保证键类型的严格弱排序:

#include <map>

int main()
{
    int x = 0, y = 1;
    bool arbitrary = false;

    std::map<int*, bool> m{
       {&x, arbitrary},
       {&y, arbitrary}
    };
}

那么,更一般地说,我们可以说带有指针键的地图是一个危险的*命题吗?或者有什么特殊的规则可以借鉴吗?

*学术上来说,就是;实际上,我不知道主流实现实际上会在比较任意指针时引发地狱。

是的,因为 std::map default comparison operator is std::less,与标准比较运算符不同,它完全是为指针类型定义的。

[comparisons#2]

For templates less, greater, less_­equal, and greater_­equal, the specializations for any pointer type yield a result consistent with the implementation-defined strict total order over pointers ([defns.order.ptr]).

实现定义的指针严格全序[defns.order.ptr]中定义为:

implementation-defined strict total ordering over all pointer values such that the ordering is consistent with the partial order imposed by the builtin operators <, >, <=, >=, and <=>

std::lessstd::map 的默认比较器)对指针有特殊处理,允许:

A specialization of std::less for any pointer type yields a strict total order, even if the built-in operator< does not.

大约

can we say that a map with pointer keys is a dangerous proposition?

所以总体来说还好

应使用 const char* 键采取额外的预防措施:

我们比较指针而不是字符串内容(主要是初学者的困惑)。

具有相同内容的 C 字符串文字不保证相等:

"literal" == "literal"; // Not guaranteed
"literal" < "literal"; // false .. or true

std::map 使用 std::less 指针类型:

A specialization of std::less for any pointer type yields a strict total order, even if the built-in operator< does not. The strict total order is consistent among specializations of std::less, std::greater, std::less_equal, and std::greater_equal for that pointer type, and is also consistent with the partial order imposed by the corresponding built-in operators (<, >, <= and >=).

为了更具体的描述,我给你留下了 2 个链接:

std::less first link

std::less second link

that is; in reality I'm not aware of mainstream implementations that will actually raise hell over comparing arbitrary pointers.

取决于地狱是什么意思。地狱不仅仅是立即崩溃或用随机数据扰乱内存。它可能会给本应是确定性函数的结果带来不确定的结果。

众所周知,GCC 可以优化已知指向不同完整对象 A 和 B 的相关(虚拟)(子)对象的对象的指针比较:任何基于 &A 的内容都会与基于 [ 的任何内容进行比较=11=],甚至 &A+1,即使地址实际上是相同的。我不知道这是在 C 还是 C++ 中观察到的,但你的问题几乎是 C/C++(并且也适用于 qsort)。

也就是说,指针比较的结果取决于指针的已知来源。这意味着根据优化级别、内联上下文、翻译单元等,比较可能会给出不同的结果。

所以是的,如果您进行这些指针比较,它至少可能会在流行编译器的某些版本上崩溃。

您没有,因为 std::map 未在术语 operator< 中定义,而是在术语 std::less 中定义。