【lambda表达式传值问题研究】
lambda表达式传值问题研究
- 引用传值对象的声明周期会延长吗? ---不会
- =传值对象声明周期?
- 疑问1:这段代码为何调用3次Test的拷贝构造?
- 疑问2:=拷贝的对象内存在哪?栈空间还是堆空间?
引用传值对象的声明周期会延长吗? —不会
#include <iostream>
#include <functional>
class Fun
{
public:
std::function <int()> fun;
};
class Test
{
public:
Test()
{
std::cout << "constructor" << std::endl;
}
~Test()
{
std::cout << "destructor" << std::endl;
}
int num;
};
void function(Fun &obj)
{
int num = 666;
Test temp;
temp.num = 888;
obj.fun = [&]() ->int {
std::cout << num << "," << temp.num << std::endl;
};
}
int main()
{
Fun test;
function(test);
test.fun();
return 0;
}
输出:
constructor
destructor
666,32562 // 666能按原来的值输出只能说明原来那块地址没被使用
按 <RETURN> 来关闭窗口...
=传值对象声明周期?
答在 labdm 这个对象消失后 释放
#include <iostream>
#include <functional>
#include <thread>
class Fun
{
public:
Fun()
{
std::cout << "Fun::constructor" << std::endl;
}
~Fun()
{
std::cout << "Fun::destructor" << std::endl;
}
std::function <int()> fun;
};
class Test
{
public:
Test()
{
std::cout << "Test::constructor" << std::endl;
}
Test(const Test &obj)
{
num = 999;
std::cout << "Test::copy_constructor" << std::endl;
}
~Test()
{
std::cout << "Test::destructor" << std::endl;
}
int num;
};
void function(Fun &obj)
{
int num = 666;
Test temp;
temp.num = 888;
obj.fun = [=]() ->int {
std::cout << num << "," << temp.num << std::endl;
return 0;
};
}
void test()
{
Fun test;
function(test);
test.fun();
std::cout << "test end" << std::endl;
}
int main()
{
test();
std::this_thread::sleep_for(std::chrono::seconds(600));
return 0;
}
输出:
Fun::constructor
Test::constructor
Test::copy_constructor
Test::copy_constructor
Test::copy_constructor
Test::destructor
Test::destructor
Test::destructor
666,999
test end
Fun::destructor
Test::destructor
疑问1:这段代码为何调用3次Test的拷贝构造?
lambda表达式其实就是编译器给你生成了个对象,这个对象的一个成员就是=捕捉的变量,多以调用了一次拷贝构造,
在把这个lambda复制给一个function的时候由于类型不同。所以编译器的做法是 首先在等号右边把lambda构造一个临时的function对象调用了一次拷贝构造,然后把这个值复制给类的function成员变量又进行了一次调用了一次拷贝构造。
疑问2:=拷贝的对象内存在哪?栈空间还是堆空间?
拷贝的对象在lambda匿名对象里,它就是这个匿名对象的一个成员。这个lambda在哪它就在哪,如果&捕捉,编译器创建匿名对象的时候就用一个成员引用去对应这个捕捉的对象。
什么类不能拷贝构造?成员变量不能有:constexpr变量和引用类型,这个问题是面试的时候被问到的。当时不理解什么场景下类的成员要设计成引用,觉得这么设计很不安全。现在想想,可能就像这种工具类的应用场景下完美契合。