在 C++20 常量表达式中是否允许比较动态分配对象的地址?

Is comparing addresses of dynamically allocated objects allowed in C++20 constant expression?

C++20 允许在 constexpr 函数中进行堆分配,只要内存不泄漏即可。然而,GCC 和 Clang 对于比较两个动态分配对象的地址是否是常量表达式存在分歧。

以下代码片段可以用 Clang 编译,但不能用 gcc 编译。

constexpr bool foo() {
    int* a = new int(4);
    int* b = new int(4);
    bool result = a == b;
    delete a;
    delete b;
    return result;
}

constexpr bool x = foo(); // GCC:  error: '(((int*)(& heap deleted)) == ((int*)(& heap deleted)))' is not a constant expression

以下在两个编译器上都可以正常工作

constexpr bool foo2() {
    int a = 4;
    int b = 5;
    bool result = &a ==  &b;

    return result;
}

constexpr bool x = foo2();

我假设为了正确删除动态对象,编译器必须知道指针是否指向相同的对象,所以我假设这是一个 GCC 错误(或尚未完全实现) .谁能证实这个假设?还是我错了?

实例here.

编辑:奇怪的是,当我通过提供的 link 打开实时示例时,它突然也在 gcc 上编译。但是如果我将它复制粘贴到一个新的编译器资源管理器实例中,它会再次失败。或者,如果我多次重新加载它,它会每隔两次失败一次并每隔两次编译一次...

这是一个 gcc 错误 (#85428)。

[expr.const]/5 that would cause evaluation of a == b to fail to be a constant expression. The only one there in which there is any question would be the one about undefined behavior. So we could go look at [expr.eq] 中没有关于指针比较的内容:

If at least one of the operands is a pointer, pointer conversions, function pointer conversions, and qualification conversions are performed on both operands to bring them to their composite pointer type. Comparing pointers is defined as follows:

  • If one pointer represents the address of a complete object, and another pointer represents the address one past the last element of a different complete object, the result of the comparison is unspecified.
  • Otherwise, if the pointers are both null, both point to the same function, or both represent the same address, they compare equal.
  • Otherwise, the pointers compare unequal.

两个指针都代表了不同的完整对象的地址,都不为null,所以就落入第三点,只是指针比较不相等。这里没有未定义或未指定的行为。

a == b 应该只产生 false.