在 lambda 函数声明中使用 auto
Using auto in lambda function declaration
什么时候可以 auto
用作用 lambda 函数初始化的变量的类型说明符?我尝试在以下程序中使用 auto
:
#include <iostream>
#include <functional>
class A
{
const std::function <void ()>* m_Lambda = nullptr;
public:
A(const std::function <void ()>& lambda): m_Lambda (&lambda) {}
void ExecuteLambda()
{
(*m_Lambda)();
}
};
void main()
{
int i1 = 1;
int i2 = 2;
const auto lambda = [&]()
{
std::cout << "i1 == " << i1 << std::endl;
std::cout << "i2 == " << i2 << std::endl;
};
A a(lambda);
a.ExecuteLambda();
}
我正在使用 Visual Studio Community 2019,当我开始执行 a.ExecuteLambda()
时,程序停止并出现以下异常:
Unhandled exception at 0x76D9B5B2 in lambda.exe:
Microsoft C ++ exception: std :: bad_function_call at memory location 0x00B5F434.
如果我将行 const auto lambda = [&]()
更改为 const std::function <void ()> lambda = [&]()
,它会完美运行。为什么不允许使用auto
?可以更改某些内容以允许使用它吗?
您在 A
对象中存储了一个 悬挂 std::function
指针。
lambda 表达式不是 std::function
对象,它是编译器定义的类型,可以 分配 给 std::function
对象。
当您使用 auto
声明 lambda
时,它会获得一个唯一的类型。要将此 lambda
绑定到 A
构造函数的参数,将创建一个 temporary std::function
对象,您正在存储指向该对象的指针。但是,temporary 在构造函数退出时被销毁,这就是为什么在尝试执行 std::function
.
时会出现异常的原因
当您将 lambda
的声明更改为 std::function
时,A
构造函数的参数能够按原样绑定到该对象,并且不会创建临时对象。
您应该按值而不是指针传递和存储 std::function
对象,例如:
#include <iostream>
#include <functional>
class A
{
std::function<void()> m_Lambda;
public:
A(std::function<void()> lambda): m_Lambda(lambda) {}
void ExecuteLambda()
{
m_Lambda();
}
};
int main()
{
int i1 = 1;
int i2 = 2;
const auto lambda = [&]()
{
std::cout << "i1 == " << i1 << std::endl;
std::cout << "i2 == " << i2 << std::endl;
};
A a(lambda);
a.ExecuteLambda();
return 0;
}
lambda 表达式不会产生 std::function
。相反,它创建了一个未命名的唯一 class 类型,并且具有 operator()
的重载。当您将 lambda 传递给 A
的构造函数时,它会创建一个临时 std::function
对象,并存储指向该临时对象的指针。当 A
的构造函数结束时,该临时对象被销毁,留下一个悬空指针。
要解决此问题,只需摆脱使用指针即可。那看起来像
#include <iostream>
#include <functional>
class A
{
std::function <void ()> m_Lambda;
public:
A(const std::function <void ()> lambda): m_Lambda (lambda) {}
void ExecuteLambda()
{
m_Lambda();
}
};
void main()
{
int i1 = 1;
int i2 = 2;
const auto lambda = [&]()
{
std::cout << "i1 == " << i1 << std::endl;
std::cout << "i2 == " << i2 << std::endl;
};
A a(lambda);
a.ExecuteLambda();
}
什么时候可以 auto
用作用 lambda 函数初始化的变量的类型说明符?我尝试在以下程序中使用 auto
:
#include <iostream>
#include <functional>
class A
{
const std::function <void ()>* m_Lambda = nullptr;
public:
A(const std::function <void ()>& lambda): m_Lambda (&lambda) {}
void ExecuteLambda()
{
(*m_Lambda)();
}
};
void main()
{
int i1 = 1;
int i2 = 2;
const auto lambda = [&]()
{
std::cout << "i1 == " << i1 << std::endl;
std::cout << "i2 == " << i2 << std::endl;
};
A a(lambda);
a.ExecuteLambda();
}
我正在使用 Visual Studio Community 2019,当我开始执行 a.ExecuteLambda()
时,程序停止并出现以下异常:
Unhandled exception at 0x76D9B5B2 in lambda.exe:
Microsoft C ++ exception: std :: bad_function_call at memory location 0x00B5F434.
如果我将行 const auto lambda = [&]()
更改为 const std::function <void ()> lambda = [&]()
,它会完美运行。为什么不允许使用auto
?可以更改某些内容以允许使用它吗?
您在 A
对象中存储了一个 悬挂 std::function
指针。
lambda 表达式不是 std::function
对象,它是编译器定义的类型,可以 分配 给 std::function
对象。
当您使用 auto
声明 lambda
时,它会获得一个唯一的类型。要将此 lambda
绑定到 A
构造函数的参数,将创建一个 temporary std::function
对象,您正在存储指向该对象的指针。但是,temporary 在构造函数退出时被销毁,这就是为什么在尝试执行 std::function
.
当您将 lambda
的声明更改为 std::function
时,A
构造函数的参数能够按原样绑定到该对象,并且不会创建临时对象。
您应该按值而不是指针传递和存储 std::function
对象,例如:
#include <iostream>
#include <functional>
class A
{
std::function<void()> m_Lambda;
public:
A(std::function<void()> lambda): m_Lambda(lambda) {}
void ExecuteLambda()
{
m_Lambda();
}
};
int main()
{
int i1 = 1;
int i2 = 2;
const auto lambda = [&]()
{
std::cout << "i1 == " << i1 << std::endl;
std::cout << "i2 == " << i2 << std::endl;
};
A a(lambda);
a.ExecuteLambda();
return 0;
}
lambda 表达式不会产生 std::function
。相反,它创建了一个未命名的唯一 class 类型,并且具有 operator()
的重载。当您将 lambda 传递给 A
的构造函数时,它会创建一个临时 std::function
对象,并存储指向该临时对象的指针。当 A
的构造函数结束时,该临时对象被销毁,留下一个悬空指针。
要解决此问题,只需摆脱使用指针即可。那看起来像
#include <iostream>
#include <functional>
class A
{
std::function <void ()> m_Lambda;
public:
A(const std::function <void ()> lambda): m_Lambda (lambda) {}
void ExecuteLambda()
{
m_Lambda();
}
};
void main()
{
int i1 = 1;
int i2 = 2;
const auto lambda = [&]()
{
std::cout << "i1 == " << i1 << std::endl;
std::cout << "i2 == " << i2 << std::endl;
};
A a(lambda);
a.ExecuteLambda();
}