在 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
.
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
.