实战c++中的智能指针unique_ptr系列-- unique_ptr与lambda的错误结合(尤其是捕获lambda中的unique_ptr)

lambda表达式是C++11新引入的东西,给我们带来了很多的方便,使得代码简洁明了。

但是当我们把unique_ptr和lambda表达式结合的时候,错误就往往会出现,而且是致命的。

直接看看下面的代码:

#include "stdafx.h"
#include <memory>
#include <vector>
#include <algorithm>

class Message {
public:
     Message() {}
};

int main(int argc, char* argv[])
{
     std::vector<std::unique_ptr<Message>>messages;

     for (int i = 0; i < 1000; i++) {
          std::unique_ptr<Message> testMess;
          messages.push_back(std::move(testMess));  
     }

     std::for_each(messages.begin(), messages.end(),
                [](std::unique_ptr<Message> testMess) {     
        // do something stupid
     });

   return 0;
}

但是不幸的是,这段代码编译就会产生错误,但也算是幸运的:

d:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm(24): error C2280:std::unique_ptr<Message,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)”: 尝试引用已删除的函数

简单分析
我们在lambda表达式中使用的是按值传递;
按值传递就会产生副本,就会产生一个unique_ptr的copy;
但是我们知道的,这显然是错误。

解决方法很简单,就是按引用传递替代按指针传递:

#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>

class Message {
public:
    Message() {}
};

int main(int argc, char* argv[])
{
    std::vector<std::unique_ptr<Message>>messages;

    for (int i = 0; i < 1000; i++) {
        std::unique_ptr<Message> testMess;
        messages.push_back(std::move(testMess));
    }

    std::for_each(messages.begin(), messages.end(),
        [](std::unique_ptr<Message> &testMess) {
        // do something stupid
    });

    return 0;
}

上面的内容只是算个开胃菜,如果我们想在lambda表达式中捕获unique_ptr,又会如何呢?

十分优雅的写下如下代码:

#include<iostream>
#include<memory>
#include<string>
int main()
{
    auto str = std::make_unique<std::string>("my string");
    auto lambda = [capturedStr = std::move(str)]{
        std::cout << *capturedStr.get() << std::endl;
    };
    lambda();
    return 0;
}

一切很完美,编译 运行 输出正确。

接下来,再干点事儿:

#include<iostream>
#include<memory>
#include<string>
int main()
{
    auto str = std::make_unique<std::string>("my string");
    auto lambda = [capturedStr = std::move(str)] {
        std::cout << *capturedStr.get() << std::endl;
        auto str2 = std::move(capturedStr);
        std::cout << *str2 << std::endl;
    };
    lambda();
    return 0;
}

恭喜你,编译错误。

原因为何呢?为什么 auto str2 = std::move(capturedStr);会错误呢?
这就是lambda表达式的知识了:
lambda表达式默认是const的,我们当然不能std::move一个const对象。

解决方法也很简单,就是加入关键字mutable
程序如下,运行完好:

#include<iostream>
#include<memory>
#include<string>
int main()
{
    auto str = std::make_unique<std::string>("my string");
    auto lambda = [capturedStr = std::move(str)] ()mutable {
        std::cout << *capturedStr.get() << std::endl;
        auto str2 = std::move(capturedStr);
        std::cout << *str2 << std::endl;
    };
    lambda();
    return 0;
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
unique_ptrC++11引入的智能指针类,定义在<memory>头文件。它可以通过指定对象类型作为模板参数来创建。例如,unique_ptr<int>是指向int类型对象的指针,unique_ptr<double>是指向double类型对象的指针。\[1\] unique_ptr具有独占对象所有权的特点,即同一时间只能有一个unique_ptr指向一个对象,不能进行复制操作,只能进行移动操作。这意味着两个unique_ptr不能指向同一个对象。\[2\] unique_ptr还可以使用自定义的删除器(deleter),通过lambda表达式或函数指针来指定删除对象的方式。例如,在创建unique_ptr时可以指定一个lambda表达式作为删除器,用于在unique_ptr销毁时释放对象。\[3\] 总结来说,unique_ptrC++一种独占所有权的智能指针,它提供了自动释放对象的功能,并且可以通过指定对象类型和自定义删除器来灵活地管理资源。 #### 引用[.reference_title] - *1* [C++ 智能指针unique_ptr](https://blog.csdn.net/weixin_42322256/article/details/124058138)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [智能指针 unique_ptr 详解](https://blog.csdn.net/fuhanghang/article/details/113928128)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一苇渡江694

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值