是否将 nullptr 取消引用到 lambda 函数未定义的行为?
Is dereferencing nullptr to lambda function undefined behaviour?
如 pfultz2 所示,有一个 lambda 函数静态初始化的解决方法。其中一个步骤提到取消引用指向 lambda 函数类型的指针的 nullptr。
template <typename T> typename std::remove_reference <T>::type * addr (T && t)
{
return & t;
}
constexpr auto f = true ? nullptr : addr ([] (int arg) { return arg + 1; });
int main ()
{
assert (((*f) (1) == 2));
}
通过规范和另一个问题 我无法理解 *f
是否是未定义的行为。规范中的哪些部分会使这种不是未定义的行为?
What sections in the spec would make this not undefined behaviour?
这个问题问错了。没有标准的一部分明确表示它是未定义的,而标准的另一部分却说它已定义的程序。
您 link 的问题是关于获取取消引用的空指针的地址。那不是你在这里做的。您在这里所做的是通过空指针调用成员函数。 (*f) (1)
表示 f->operator() (1)
。这是明确无效的,如果 -fsanitize=undefined
选项,将在 运行 时使用 GCC 或 clang 失败,否则可能会由于优化器假设 f != null
.
而导致不可预测的行为
引用自N4140(大致为C++14),但在其他版本的标准中没有区别:
9.3.1 Nonstatic member functions [class.mfct.non-static]
2 If a non-static member function of a class X
is called for an object that is not of type X
, or of a type derived from X
, the behavior is undefined.
如 pfultz2 所示,有一个 lambda 函数静态初始化的解决方法。其中一个步骤提到取消引用指向 lambda 函数类型的指针的 nullptr。
template <typename T> typename std::remove_reference <T>::type * addr (T && t)
{
return & t;
}
constexpr auto f = true ? nullptr : addr ([] (int arg) { return arg + 1; });
int main ()
{
assert (((*f) (1) == 2));
}
通过规范和另一个问题 *f
是否是未定义的行为。规范中的哪些部分会使这种不是未定义的行为?
What sections in the spec would make this not undefined behaviour?
这个问题问错了。没有标准的一部分明确表示它是未定义的,而标准的另一部分却说它已定义的程序。
您 link 的问题是关于获取取消引用的空指针的地址。那不是你在这里做的。您在这里所做的是通过空指针调用成员函数。 (*f) (1)
表示 f->operator() (1)
。这是明确无效的,如果 -fsanitize=undefined
选项,将在 运行 时使用 GCC 或 clang 失败,否则可能会由于优化器假设 f != null
.
引用自N4140(大致为C++14),但在其他版本的标准中没有区别:
9.3.1 Nonstatic member functions [class.mfct.non-static]
2 If a non-static member function of a class
X
is called for an object that is not of typeX
, or of a type derived fromX
, the behavior is undefined.