考虑以下代码(请参阅https://rextester.com/OAWUM62639):
#include <iostream>
#include <functional>
void foo( int x_ )
{
std::cout<< "Value: " << x_ << "\n";
}
void something( void *c )
{
auto *f = static_cast<std::function<void()>*>(c);
(*f)();
}
int main()
{
int x = 2;
std::function<void()> lmbd = [=](){ foo(x); }; // lambda with capture.
something( &lmbd ); // is this implicit conversion safe?
}
从
std::function<void()>
到 void*
的隐式转换安全吗?
代码似乎按预期运行,但我不确定 C++11 标准在这种情况下强加的基本规则。
这里有一个类似的问题:如何将 std::function 对象传递给采用函数指针的函数?,但接受的答案建议使用
reinterpret_cast
。在这种情况下,reinterpret_cast
是必需的吗(参见https://rextester.com/ZUY69757)?
从 std::function
到 void* 的隐式转换安全吗?
显示的所有代码都是安全的。
一般来说,对于任何类型为
T
的对象,将指向它的指针指向 static_cast
然后返回到 void*
来使用它是完全可以的。这种界面的棘手之处是:
T*
会丢失类型信息,但您
必须转换回确切的原始类型才能使用指向的对象。转换为任何其他类型可能会导致未定义的行为。因此,通常此类接口唯一合理的行为是仅复制指针值本身并将指针传递回用户提供的上下文,该上下文知道实际类型。
void*
指针始终纯粹在观察。它不具有任何所有权。因此,调用者必须确保实际对象(即
void*
)的寿命比 lmbd
对 void*
指针的任何使用都长。如果 something
将指针存储在某处,例如稍后的回调,这可能会变得棘手。