【问题标题】:Does this c++11 lambda code invoke undefined behavior?这个 c++11 lambda 代码会调用未定义的行为吗?
【发布时间】:2014-08-04 14:59:51
【问题描述】:

C++11 §5.1.2/6

没有 lambda 捕获的 lambda 表达式的闭包类型具有 [...] 转换函数 [...]。这个转换函数的返回值应该是一个函数的地址,当被调用时,它与调用闭包类型的函数调用运算符具有相同的效果。

注意:这并不是说转换总是会返回相同类型的 same 值。那么,以下程序是否与 UB 它所暗示的所有意义破坏相冲突?

int main() {
  auto f = []{};
  return ((+f) == (+f));
} 

注意:如果有任何真正的编译器提供除true 之外的任何内容,我会感到非常惊讶,但问题是编译器是否可以合法 做其他事情?


编辑:

C++11 §1.3.24

未定义的行为

本国际标准没有要求的行为 [注意:当本国际标准省略任何明确的行为定义或程序使用错误的构造或错误数据时,可能会出现未定义的行为

【问题讨论】:

  • 你确定一元 + 允许用于 lambdas 吗?除此之外,您的程序格式正确,并且由于从main() 返回 1,因此仅具有实现定义的行为。
  • @Deduplicator:允许。 lambda 被隐式转换为指针,并且指针可能对它执行了++ 是此上下文中的标识函数)。

标签: c++ c++11 lambda language-lawyer undefined-behavior


【解决方案1】:

不,它既不是未定义的,也不是未指定的。您不提前知道结果是否总是相同truefalse),但没有任何内容意味着您的程序具有未定义的行为或结果属于“未指定值”的定义。

简而言之,这与调用 rand() 甚至调用 &someVariable 一样 UB。

【讨论】:

  • rand() 的调用绝对是我会归类为未指定的:[defns.unspecified]“行为,对于格式良好的程序结构和正确的数据,这取决于实现”。跨度>
  • 不,用户输入不是“未指定的行为”,因为它不依赖于实现,而是依赖于执行环境(以及......惊喜......来自用户)。
  • 如果不是实现,它取决于什么?该标准确实没有精确定义将返回哪个特定函数指针(只是取消引用和调用结果函数指针的行为)。 是未指定行为的来源。
  • @LightnessRacesinOrbit:您的意思是使用indeterminate 值吗?因为unspecified 值只会使结果最差unspecified
  • 我从来没有说过不确定的价值。我说的是未指明的行为。 &someVariable 没有未指定的行为。打印&someVariable,或将&someVariable 转换为一个整数值并将其与某物进行比较,等等……这些具有未指定的行为。如果你从不做这些事情中的任何一件,你的程序就会有完全由标准规定的行为。如果你这样做,那么你突然就会有未指明的行为。
【解决方案2】:

可以测试(相同类型的)函数指针是否相等,即使它们彼此不相等(否则函数指针的 == 将是什么意思)。

来自[expr.eq]

可以比较相同类型的指针(指针转换后)是否相等。相同类型的两个指针比较相等当且仅当它们都为空,都指向同一个函数,或者都表示相同的地址(3.9.2)。

您的程序中没有任何未定义的行为。您的程序具有未指定的行为,因为相等性检查可能返回 truefalse,但您的程序无法召唤鼻恶魔、发射导弹、擦除硬盘驱动器或与未定义行为相关的任何其他讨厌的行为.

【讨论】:

  • 参见第 1.3.24 节的引文了解什么是未定义行为。
  • 我知道什么是未定义的行为...如本答案所述,您的程序具有 unspecified 行为,而不是 undefined 行为。
  • 我不认为它是未指定的。它可能并不总是相同的,但这不是未指定的意思。 rand() 的值是“未指定”吗? getSomeInputFromTheUser()的?没有。
  • +f 与未指定的 +f 相比如何?如果f 是 lambda,它们怎么可能不相等?
  • @Deduplicator:因为标准不要求转换为函数指针总是为相同的 lambda 返回相同的函数指针。
猜你喜欢
  • 2011-08-25
  • 1970-01-01
  • 2019-12-12
  • 1970-01-01
  • 2015-05-26
  • 2013-08-25
  • 1970-01-01
  • 1970-01-01
  • 2022-01-09
相关资源
最近更新 更多