指针如何完全有序? C++中的指针一般只能比较相等。相比之下,只有指向同一完整对象的子对象(例如数组元素)的两个指针才允许小于比较
因此,给定指针如何完全有序? C++中的指针一般只能比较相等。相比之下,只有指向同一完整对象的子对象(例如数组元素)的两个指针才允许小于比较,c++,pointers,predicate,standard-library,C++,Pointers,Predicate,Standard Library,因此,给定T*p,*q,通常对p
T*p,*q
,通常对p
进行评估是非法的
标准库包含函子类模板std::less
等,这些模板包装了内置运算符
在指针不形成全局总顺序的目标上,是否可以实现标准库
对。给定任何一个有限集,你总是可以在它上面定义一个任意的总阶
考虑一个简单的例子,其中只有五个可能的不同指针值。让我们称之为O(对于nullptr),γ,ζ,χ,ψ1
假设四个非空指针中的两个不同指针对不能与相比,在大多数具有平坦地址空间的平台上,它们可以简单地在指针之间进行数字比较。在无法实现这一点的平台上,实现者必须想出一些其他方法来建立在std::less
中使用的总顺序,但他们可能会对使用更有效的方法。问题是分段体系结构,其中内存地址有两部分:段和偏移量。将这些片段转换成某种线性形式“非常容易”,但这需要额外的代码,而决策是不为操作符施加开销指针可以完全有序吗?不是便携式的,标准的C++。那是
为什么标准要求实施来解决问题,而不是
你。对于指针的任何给定表示形式,都应该是可能的
定义任意的总排序,但如何定义将取决于
指针的表示形式
对于具有平坦地址空间和字节寻址的计算机,只需
将指针视为大小相似的整数或无符号指针
整数通常就足够了;这是大多数编译器将处理的方式
对象内部的比较也是如此,所以在这样的机器上,没有
图书馆需要专门化std::less
等“未指定”
行为只是碰巧做了正确的事情
对于字寻址机器(至少有一台仍在使用中)
生产),可能需要将指针转换为void*
在编译器本机比较开始工作之前
对于具有分段体系结构的机器,可能需要进行更多的工作。
在这样的机器上,通常需要将一个阵列完全放在一个阵列中
段,只需比较段中的偏移量;这意味着如果
a
和b
是两个任意指针,您可能会得到!(a
但不是a==b
。在这种情况下,编译器必须提供
针对指针的std::less
等的专门化(可能)
从指针提取段和偏移量,并执行某种操作
操纵它们
编辑:
对值得提及的其他事物:也许:C++中的保证
标准只适用于标准C++,或者在这种情况下,指针获得
从标准C++。在大多数现代系统上,很容易
mmap
同一个文件指向两个不同的地址范围,并有两个指针p
和q
,它们比较不相等,但指向同一个对象。我认为在这次讨论中缺少了一个更深层次的概念,那就是指针起源的概念
原则上,您一般不能比较指针,但应该能够比较来自同一个指针(通过算术运算)的指针。
例如,来自黑盒的指针(如对new
的不同调用)无法可靠地进行比较。
(这里的比较适用于排序,但我想严格来说,在这种情况下,平等也是定义不清的,我不确定。这将涵盖上面的mmap
案例。)
因此,这里是我尝试的一个(相当无用但概念性的)答案:指针的比较是顺序运算符适用范围内的总顺序(即,当它不是未定义时)。
好的一面是,继续比较属于/来自同一分配或单个块的指针。毕竟,如果T*p2=p1+1,它必须保持p2>p1
代码>
这类似于C++中容器迭代器的情况,如果两个迭代器来自不同的容器,比较它们就没有意义了。
编辑:肖恩家长对这个问题的看法。释义
(1) 您只能比较相同容器的指针[我认为这太强了,除了std::vector
]。
(2) 对指针使用std::less
,因此它仅用于“表示”(例如放入std::set
)。
(3) 一些编译器会抱怨比较(void?)指针。(我认为这很好,因为void*没有算术)
一些相关材料:这不是因为虚拟内存提供了线性地址空间才起作用吗?嗯,我不知道以这种方式比较指针是非法的。@R.MartinhoFernandes:很公平。如果您想要一个更具体的问题,请考虑这个变化:“是否可以在指针不形成全局、总顺序的目标上实现标准库?”@哈罗德,分段架构,16位80x86,例如。可以想象,编译器在等中仅使用远指针的偏移量部分。假设没有对象跨越段边界,但小于等,则可以使用完整的20位seg:offset。@Rook:imho比较指针通常不非法,但通常未定义。确定,那么问题是:这个任意的总顺序能与@Kerrek的子对象顺序兼容吗?不,我从来没有见过这样的要求