这是程序:
#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();
}
以下是输出:
foo constructor
executed callback
foo destructor
foo constructor
executed callback
foo destructor
foo destructor
从字面上看,为什么没有&的auto关键字不应该仍然检测到我正在将lambda传递到期望引用的std::函数中?我用MSVC,Clang和GCC测试了这一点,它们都有这种行为。
额外的析构函数调用发生在lambda执行结束时
1条答案
按热度按时间nbysray51#
auto
本身永远不会推导出引用类型。你可以把你的
std::function::operator()
想象成这样:由于
callback
通过值接受其参数,因此其参数的类型被推断为Foo
,并且f
用于初始化一个新对象,该对象是f
引用的对象的副本。当callback
结束时,该对象超出范围并被销毁。