局部变量指针在生命周期结束后的编译时比较
Compile-time comparison of pointers to local variables after their end of life
从 C++17 开始,可以定义一个 constexpr
函数,该函数将 return 指向其局部变量的指针。调用者将因此在对象生命周期结束后获得指向对象的指针。
显然不能取消引用此类指针以避免未定义的行为。但是将它们进行平等比较合法吗?
考虑一个例子:
constexpr auto f() {
char c = 0;
auto p = &c;
return p;
};
int main() {
static_assert( ( f() == f() ) == ( f() == f() ) ); //ok everywhere
static_assert( f() == f() ); //true in GCC, false in Clang
}
第一个static_assert
被所有编译器接受(如果有一些未定义的行为,不会出现任何警告),它基本上检查f() == f()
给出一致的结果true
或false
在每个编译器中。
GCC 说 f() == f()
是正确的,而 Clang 坚持 f() != f()
(这在编译时看起来更合乎逻辑)。演示:https://gcc.godbolt.org/z/YG1jonoG7
哪个编译器(如果有的话)就在这里?
奇怪的是,根据 [basic.stc]/4,实现定义:f
返回的指针 无效,所以比较它们可能会做一些坏事。当然,这里的 space 可能性并不十分清楚:脚注提到运行时错误,通常与未定义的行为混为一谈,但在不断评估期间,人们会期望可靠地 失败 评估(将被报告为“static_assert
表达式不是常量”)。据推测,实现需要在此处记录他们的选择,但我怀疑他们中的任何一个都有意义地解决了这种特殊情况。
从 C++17 开始,可以定义一个 constexpr
函数,该函数将 return 指向其局部变量的指针。调用者将因此在对象生命周期结束后获得指向对象的指针。
显然不能取消引用此类指针以避免未定义的行为。但是将它们进行平等比较合法吗?
考虑一个例子:
constexpr auto f() {
char c = 0;
auto p = &c;
return p;
};
int main() {
static_assert( ( f() == f() ) == ( f() == f() ) ); //ok everywhere
static_assert( f() == f() ); //true in GCC, false in Clang
}
第一个static_assert
被所有编译器接受(如果有一些未定义的行为,不会出现任何警告),它基本上检查f() == f()
给出一致的结果true
或false
在每个编译器中。
GCC 说 f() == f()
是正确的,而 Clang 坚持 f() != f()
(这在编译时看起来更合乎逻辑)。演示:https://gcc.godbolt.org/z/YG1jonoG7
哪个编译器(如果有的话)就在这里?
奇怪的是,根据 [basic.stc]/4,实现定义:f
返回的指针 无效,所以比较它们可能会做一些坏事。当然,这里的 space 可能性并不十分清楚:脚注提到运行时错误,通常与未定义的行为混为一谈,但在不断评估期间,人们会期望可靠地 失败 评估(将被报告为“static_assert
表达式不是常量”)。据推测,实现需要在此处记录他们的选择,但我怀疑他们中的任何一个都有意义地解决了这种特殊情况。