在C ++中是否有一种可移植的替代指针关系比较?

时间:2010-12-26 08:52:36

标签: c++ pointers comparison

我缺乏语言的行业经验。但是在业余时间我遇到过几个需要比较指针的地方,最好是标准定义的行为。

第一种情况,如果我决定在我的应用程序中使用有序二叉树作为容器(而不是哈希表)并且我希望相等是对象的标识(即相等意味着相同的实例),那么我发现没有可移植的方式这样做。

其次,如果我想测试“完整对象”和它们的子对象之间的包含关系,我似乎再没有可移植的方法。那就是如果我有两个void *指针“p”和“q”,并且我有“q”所指向的对象的大小,我看不出来测试“p”是否是非静态成员变量“q”与否。我没有从标准中的第5.9段(“关系运营商”)中找到鼓励。例如,后一种情况出现在此提升论坛post的垃圾收集器中。我喜欢这个一般的想法并开始探索它,但是某些部分似乎以不可移植的方式使用指针和分配语义。

这就是我想知道如何从以下代码中使contains函数可移植:

#include <stddef.h>
#include <assert.h>

struct A {
    int x;
} a;

struct B {
    int y;
} b;

bool contains(const void *outer, size_t size, const void *inner)
{
    return (outer <= inner) &&
        (inner < static_cast<const char *>(outer) + size);
}

int main()
{
    assert(contains(&a, sizeof(a), &a.x));
    assert(contains(&b, sizeof(b), &b.y));
    assert(!contains(&a, sizeof(a), &b.y));
    assert(!contains(&b, sizeof(b), &a.x));
}

谢谢和最诚挚的问候。

PS:
好的,在再次查阅标准之后,我看到它明确指出,正如GMan在他的回答中所说,lessless_equal之类的函子提供了指针的总排序。我认为这也暗示了排序与内置比较运算符<<=一致,但这一点可以更迂腐地解决。当指针不指向同一数组或同一对象的子对象时,内置运算符是不可预测的。我的意思是,这个总顺序中的独特性测试是什么 - 指针的二进制表示?例如,如果没有以明确定义的方式与内置运算符进行比较,那么void*指针的总顺序中的不相同是什么意思?

对于具有相同访问控制的成员变量,标准在内存中定义它们的顺序,即通过指针比较观察时。它是对象类型定义中的外观顺序。从内置比较运算符的角度来看,第一个成员变量的地址最小,最后一个成员变量的地址最大。此外,在关于类型的部分中,陈述了“平凡可复制类型”的对象将在&运算符的值和以下sizeof字符之间的范围内布置在存储器中。现在让我们假设仿函数提供了指向不同对象的指针的总顺序。这是不是意味着,即使无意中,标准意味着上面代码段的行为,如果使用仿函数而不是contains函数中的内置运算符?

只是想明确一点 - 如果标准有遗漏,或者只是需要澄清,或者它为指针比较的实现留下了灵活性。

1 个答案:

答案 0 :(得分:6)

我不太确定你要求的是什么(例如,你到底想要完成什么?),但我认为这是你想知道的:

greater中定义的关系仿函数greater_equallessless_equal<functional>会产生任何指针类型的总排序,即使构建了在关系运算符中没有。

那是:

#include <functional>
#include <iostream>

int main()
{
    int i, *j = &i;    
    int k, *l = &k;

    std::cout << std::boolalpha << std::less<int*>()(j, l) << std::endl;
}

定义明确。 (注意输出是实现定义的,但 保证总排序。)

关联容器谓词默认为std::less,因此可以将指针用作键。