局部变量指针在生命周期结束后的编译时比较

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()给出一致的结果truefalse 在每个编译器中。

GCC 说 f() == f() 是正确的,而 Clang 坚持 f() != f() (这在编译时看起来更合乎逻辑)。演示:https://gcc.godbolt.org/z/YG1jonoG7

哪个编译器(如果有的话)就在这里?

奇怪的是,根据 [basic.stc]/4,实现定义f 返回的指针 无效,所以比较它们可能会做一些坏事。当然,这里的 space 可能性并不十分清楚:脚注提到运行时错误,通常与未定义的行为混为一谈,但在不断评估期间,人们会期望可靠地 失败 评估(将被报告为“static_assert 表达式不是常量”)。据推测,实现需要在此处记录他们的选择,但我怀疑他们中的任何一个都有意义地解决了这种特殊情况。