这是程序:
#include <iostream>
#include <functional>
struct Foo
{
inline Foo() {
std::cout << "foo constructor" << std::endl;
}
inline ~Foo() {
std::cout << "foo destructor" << std::endl;
}
};
void NotBroken()
{
Foo foo;
std::function<void(Foo&)> callback;
callback = [](auto&) { // <- notice the auto&
std::cout << "executed callback" << std::endl;
};
callback(foo);
}
void TotallyBroken()
{
Foo foo;
std::function<void(Foo&)> callback;
callback = [](auto) { // <- notice the auto without &
std::cout << "executed callback" << std::endl;
};
callback(foo);
}
int main()
{
NotBroken();
std::cout << std::endl;
TotallyBroken();
}
Run Code Online (Sandbox Code Playgroud)
这是输出:
foo constructor
executed callback
foo destructor
foo constructor
executed callback
foo destructor
foo destructor
Run Code Online (Sandbox Code Playgroud)
从字面上看,为什么不带 & 的 auto 关键字不应该仍然检测到我将 lambda 传递到需要引用的 std::function 中?我用 MSVC、Clang 和 GCC 对此进行了测试,它们都有这种行为。
额外的析构函数调用发生在 lambda 执行结束时(仅供参考)
auto其本身永远不会推导出引用类型。
你可以把你std::function::operator()想象成这样:
void operator()(Foo& f)
{
callback(f);
}
Run Code Online (Sandbox Code Playgroud)
由于callback按值接受其参数,因此其参数的类型被推导为Foo并f用于初始化一个新对象,该新对象是 引用的对象的副本f。当callback结束时,该对象超出范围并被销毁。
| 归档时间: |
|
| 查看次数: |
77 次 |
| 最近记录: |