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
,与标准比较运算符不同,它完全是为指针类型定义的。
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::less(std::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 个链接:
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
中定义。
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
,与标准比较运算符不同,它完全是为指针类型定义的。
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::less(std::map
的默认比较器)对指针有特殊处理,允许:
A specialization of
std::less
for any pointer type yields a strict total order, even if the built-inoperator<
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 个链接:
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
中定义。