gpt4 book ai didi

c++ - 为什么 lambda nullptr 取消引用在这种情况下有效?

转载 作者:行者123 更新时间:2023-11-27 22:32:23 25 4
gpt4 key购买 nike

我在运行代码时看到过类似的模式并自行尝试过,一切正常。这里特别有趣的一点是,我希望 (*(T*) nullptr) () 在运行时失败,但事实并非如此。这里是否有未定义的行为以及它为什么起作用?

template<typename T>
inline static int var = (*(T*) nullptr) ();

template<typename T>
int getvar (const T&)
{
return var<T>;
}

int main ()
{
int x = getvar ([]() { return 5; });
return 0;
}

谢谢!

最佳答案

是的,这个程序有未定义的行为。 lambda 表达式的结果是未命名类类型的右值 [expr.prim.lambda.closure]/1有一个重载的函数调用运算符 [expr.prim.lambda.closure]/3 .因此,您在此处的示例中实质上正在做的事情

(*(T*) nullptr) ()

您是否正在对一个不存在的对象调用 lambda 类型的 operator ()(这是一个非静态成员函数)。您可以在此处找到有关为什么这是 UB 的更多详细信息:When does invoking a member function on a null instance result in undefined behavior?

虽然您肯定正在调用未定义的行为,但这种未定义的行为几乎肯定不会在您的特定示例中出现崩溃。原因很简单:lambda 的主体不访问类的任何成员,所以即使 operator () 是用 nullptr 调用的 this,它永远不会尝试访问基于该指针的任何内存。 lambda 的类型甚至没有任何成员,因为您的 lambda 不捕获任何内容。此外,在优化构建中,人们会期望编译器简单地从这个示例程序中优化掉 x,因为它没有任何可观察到的行为......

如果您将 var 模板设为 constexpr,编译器将拒绝编译它,因为用于初始化变量的表达式不是常量表达式,因为它会调用未定义的行为[expr.const]/2.6 ……

如果我们稍微修改一下您的示例,使 lambda 有一个成员,然后我们在 lambda 主体中访问该成员

template<typename T>
int getvar (const T&)
{
return (*(T*) nullptr) ();
}

int main ()
{
return getvar ([x = 42]() { return x; });
}

你很可能会得到一个实际上崩溃的程序......

关于c++ - 为什么 lambda nullptr 取消引用在这种情况下有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59338408/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com