当前位置: 首页 > article >正文

【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变量和引用类型,这个问题是面试的时候被问到的。当时不理解什么场景下类的成员要设计成引用,觉得这么设计很不安全。现在想想,可能就像这种工具类的应用场景下完美契合。


http://www.kler.cn/a/17860.html

相关文章:

  • C#程序开发,检测当前电脑已经安装的软件目录
  • 后端:Aop 面向切面编程
  • 大语言模型在序列推荐中的应用
  • 【go从零单排】Rate Limiting限流
  • 【电力系统】永磁同步电机调速系统带有扰动观测器
  • 25浙江省考-专项刷题(资料分析)-错题本
  • node.js+vue鲜花销售网站
  • 拥抱生成式大模型 -- langchain篇 (博客搬家至知乎,同步更新)
  • Reference Type 解析 this 丢失问题
  • 极简Python--列表
  • windows下部署GTK环境
  • 一个让人类窒息的AI工具,或许未来人工智能真的能代替人类!
  • 软件架构师的修炼之道
  • CE游戏特例说明
  • 提升V-Ray渲染效率的五个实用技巧!
  • AIGC:【LLM(二)】——LangChain:由LLMs驱动的应用开发框架
  • 【JAVA】 static与final的应用
  • Flask使用Flask-SQLAlchemy对数据库操作详解二(配置、表与表之间一对一、多对一、多对多关系及增删改查参数和代码详细总结)
  • 如何把握未来增长话语权,全链路数字化运营有解
  • 设计原则之【迪米特法则】
  • 测度与积分 Measures and Integration学习笔记
  • 神经网络:Zero2Hero 1
  • 【Linux-进程通信1】管道
  • 剑指 Offer 28. 对称的二叉树
  • expected ‘(‘ after 、error: use of undeclared identifier ‘PRESERVE8‘
  • 【华为机试】——HJ4 字符串分隔