如果我将可变 lambda 作为 const 引用传递给函数,会发生什么情况?
What will happen if I pass a mutable lambda to a function as const reference?
当我将可变 lambda 作为 const 引用传递时,代码实际上做了什么?
为什么编译器不报错,这是未定义的操作吗?
为什么 f1 和 f2 不同,f1 使用 std::function<void()>
而 f2 使用 auto
?
我发现了一个类似的问题,但我还是不太明白
#include <iostream>
#include <functional>
void call(std::function<void()> const & cb) {
cb();
cb();
}
int main() {
std::function<void()> f1 = [a = 0] () mutable {
std::cout << ++a << std::endl;
};
call(f1); // prints 1 2
call(f1); // prints 3 4
auto f2 = [a = 0] () mutable {
std::cout << ++a << std::endl;
};
call(f2); // prints 1 2
call(f2); // prints 1 2
}
在第一种情况下,call(f1)
的两个调用都使用相同的 std::function<void()>
实例。
在第二种情况下,call(f2);
隐式转换形式 lambda 到 std::function<void()>
启动并创建相应的临时对象。所以第二次调用使用临时对象的新副本。
Try transform this code in cppinsights 以查看更多详细信息。
int main()
{
class __lambda_10_32
{
public:
inline /*constexpr */ void operator()()
{
std::cout.operator<<(++a).operator<<(std::endl);
}
private:
int a;
public:
// inline /*constexpr */ __lambda_10_32(const __lambda_10_32 &) noexcept = default;
// inline /*constexpr */ __lambda_10_32(__lambda_10_32 &&) noexcept = default;
__lambda_10_32(const int & _a)
: a{_a}
{}
};
std::function<void ()> f1 = std::function<void ()>(__lambda_10_32{0});
call(f1);
call(f1);
class __lambda_16_15
{
public:
inline /*constexpr */ void operator()()
{
std::cout.operator<<(++a).operator<<(std::endl);
}
private:
int a;
public:
// inline /*constexpr */ __lambda_16_15(const __lambda_16_15 &) noexcept = default;
// inline /*constexpr */ __lambda_16_15(__lambda_16_15 &&) noexcept = default;
__lambda_16_15(const int & _a)
: a{_a}
{}
};
__lambda_16_15 f2 = __lambda_16_15{0};
call(std::function<void ()>(__lambda_16_15(f2)));
call(std::function<void ()>(__lambda_16_15(f2)));
return 0;
}
当我将可变 lambda 作为 const 引用传递时,代码实际上做了什么?
为什么编译器不报错,这是未定义的操作吗?
为什么 f1 和 f2 不同,f1 使用 std::function<void()>
而 f2 使用 auto
?
我发现了一个类似的问题,但我还是不太明白
#include <iostream>
#include <functional>
void call(std::function<void()> const & cb) {
cb();
cb();
}
int main() {
std::function<void()> f1 = [a = 0] () mutable {
std::cout << ++a << std::endl;
};
call(f1); // prints 1 2
call(f1); // prints 3 4
auto f2 = [a = 0] () mutable {
std::cout << ++a << std::endl;
};
call(f2); // prints 1 2
call(f2); // prints 1 2
}
在第一种情况下,call(f1)
的两个调用都使用相同的 std::function<void()>
实例。
在第二种情况下,call(f2);
隐式转换形式 lambda 到 std::function<void()>
启动并创建相应的临时对象。所以第二次调用使用临时对象的新副本。
Try transform this code in cppinsights 以查看更多详细信息。
int main()
{
class __lambda_10_32
{
public:
inline /*constexpr */ void operator()()
{
std::cout.operator<<(++a).operator<<(std::endl);
}
private:
int a;
public:
// inline /*constexpr */ __lambda_10_32(const __lambda_10_32 &) noexcept = default;
// inline /*constexpr */ __lambda_10_32(__lambda_10_32 &&) noexcept = default;
__lambda_10_32(const int & _a)
: a{_a}
{}
};
std::function<void ()> f1 = std::function<void ()>(__lambda_10_32{0});
call(f1);
call(f1);
class __lambda_16_15
{
public:
inline /*constexpr */ void operator()()
{
std::cout.operator<<(++a).operator<<(std::endl);
}
private:
int a;
public:
// inline /*constexpr */ __lambda_16_15(const __lambda_16_15 &) noexcept = default;
// inline /*constexpr */ __lambda_16_15(__lambda_16_15 &&) noexcept = default;
__lambda_16_15(const int & _a)
: a{_a}
{}
};
__lambda_16_15 f2 = __lambda_16_15{0};
call(std::function<void ()>(__lambda_16_15(f2)));
call(std::function<void ()>(__lambda_16_15(f2)));
return 0;
}