实战c++中的智能指针unique_ptr系列-- unique_ptr与lambda的错误结合(尤其是捕获lambda中的unique_ptr)
2015-12-28 21:06
661 查看
lambda表达式是C++11新引入的东西,给我们带来了很多的方便,使得代码简洁明了。
但是当我们把unique_ptr和lambda表达式结合的时候,错误就往往会出现,而且是致命的。
直接看看下面的代码:
但是不幸的是,这段代码编译就会产生错误,但也算是幸运的:
简单分析
我们在lambda表达式中使用的是按值传递;
按值传递就会产生副本,就会产生一个unique_ptr的copy;
但是我们知道的,这显然是错误。
解决方法很简单,就是按引用传递替代按指针传递:
上面的内容只是算个开胃菜,如果我们想在lambda表达式中捕获unique_ptr,又会如何呢?
十分优雅的写下如下代码:
一切很完美,编译 运行 输出正确。
接下来,再干点事儿:
恭喜你,编译错误。
原因为何呢?为什么 auto str2 = std::move(capturedStr);会错误呢?
这就是lambda表达式的知识了:
lambda表达式默认是const的,我们当然不能std::move一个const对象。
解决方法也很简单,就是加入关键字mutable
程序如下,运行完好:
但是当我们把unique_ptr和lambda表达式结合的时候,错误就往往会出现,而且是致命的。
直接看看下面的代码:
[code]#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; }
但是不幸的是,这段代码编译就会产生错误,但也算是幸运的:
[code]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;
但是我们知道的,这显然是错误。
解决方法很简单,就是按引用传递替代按指针传递:
[code]#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,又会如何呢?
十分优雅的写下如下代码:
[code]#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; }
一切很完美,编译 运行 输出正确。
接下来,再干点事儿:
[code]#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
程序如下,运行完好:
[code]#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; }
相关文章推荐
- Notepad++配置c++、python、java与C#
- C语言: 贪吃蛇异常退出
- Check—强大的C语言单元测试框架
- c++ 静态成员变量
- c++ inline函数
- c++中文件的读写(从一个文件读到另一个文件)
- C++中的单例模式
- C++ 类模板和模板类
- C++本质:类的赋值运算符=的重载,以及深拷贝和浅拷贝
- C++输出的精度控制
- c/c++里的 堆区 栈区 静态区 文字常量区 程序代码区(二)
- c/c++里的 堆区 栈区 静态区 文字常量区 程序代码区
- C语言项目总结
- C语言。自定义函数简单版
- C++ 模板详解(一)
- C++调用Python的配置
- Makefile VPATH && vpath 区别
- C++的二进制兼容问题(以QT为例)
- 一个通用的Trie树,标准C++实现
- C语言函数用法大全