只要内存不泄漏,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 .
编辑:奇怪的是,当我通过提供的链接打开实时示例时,它也突然在 gcc 上编译。但是如果我将它复制粘贴到一个新的编译器资源管理器实例,它又会失败。或者,如果我多次重新加载它,它会每隔一次失败一次并每隔第二次编译一次......
最佳答案
这是一个 gcc 错误 ( #85428 )。
[expr.const]/5中什么都没有这将导致 a == b
的评估不能成为一个常量表达式。唯一有任何问题的就是关于未定义行为的问题。所以我们可以去看看[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.
两个指针代表不同的完整对象的地址,都不为空,所以我们落入第三个要点,指针只是比较不相等。这里没有未定义或未指定的行为。
a == b
应该只是屈服 false
.
关于c++ - 在 C++20 常量表达式中是否允许比较动态分配对象的地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65981409/