【C++】第二十六节—C++11(中) | 右值引用和移动语义(续集)+lambda

【C++】第二十六节—C++11(中) | 右值引用和移动语义(续集)+lambda

Hi,我是云边有个稻草人,C++领域博主与你分享专业知识(*^▽^*)

《C++》本篇文章所属专栏—持续更新中—欢迎订阅~

目录

上节总览,详情见—>【C++】第二十五节—C++11 (上) | 详解列表初始化+右值引用和移动语义

本节总览

(4)右值引用和移动语义在传参中的提效

6. 类型分类

7. 引用折叠

8. 完美转发

四、lambda

1. lambda表达式语法

2. lambda的应用

3. 捕捉列表

4. lambda的原理


接着上节,正文开始——

(4)右值引用和移动语义在传参中的提效
  • 查看STL文档我们发现C++11以后容器的push和insert系列的接口否增加的右值引用版本
  • 当实参是一个左值时,容器内部继续调用拷贝构造进行拷贝,将对象拷贝到容器空间中的对象
  • 当实参是一个右值,容器内部则调用移动构造,右值对象的资源到容器空间的对象上
  • 把我们之前模拟实现的list拷贝过来,支持右值引用参数版本的push_back和insert
  • 其实这里还有一个emplace系列的接口,但是这个涉及可变参数模板,我们需要把可变参数模板讲 解以后再讲解emplace系列的接口。
// void push_back (const value_type& val); // void push_back (value_type&& val); // iterator insert (const_iterator position, value_type&& val); // iterator insert (const_iterator position, const value_type& val); int main() { std::list<bit::string> lt; bit::string s1("111111111111111111111"); lt.push_back(s1); cout << "*************************" << endl; lt.push_back(bit::string("22222222222222222222222222222")); cout << "*************************" << endl; lt.push_back("3333333333333333333333333333"); cout << "*************************" << endl; lt.push_back(move(s1)); cout << "*************************" << endl; return 0; } //可以自己分析一下运行结果 运行结果: string(char* str) string(const string& s) -- 拷贝构造 ************************* string(char* str) string(string&& s) -- 移动构造 ~string() -- 析构 ************************* string(char* str) string(string&& s) -- 移动构造 ~string() -- 析构 ************************* string(string&& s) -- 移动构造 ************************* ~string() -- 析构 ~string() -- 析构 ~string() -- 析构 ~string() -- 析构 ~string() -- 析构

下面是自己实现 list 的右值版本的push_back。注意右值在层层传递的时候属性的变化,要move保持其右值属性才能调用移动构造

// List.h // 以下代码把跟这里无关的接口都删除了,精简版 namespace bit { template<class T> struct ListNode { ListNode<T>* _next; ListNode<T>* _prev; T _data; ListNode(const T& data = T()) :_next(nullptr) , _prev(nullptr) , _data(data) { } ListNode(T&& data)//这里不需要给缺省值,有缺省值的构造函数是默认构造函数,一个类里面只能有一个默认构造函数 :_next(nullptr) , _prev(nullptr) , _data(move(data)) { } }; template<class T, class Ref, class Ptr> struct ListIterator { typedef ListNode<T> Node; typedef ListIterator<T, Ref, Ptr> Self; Node* _node; ListIterator(Node* node) :_node(node) { } Self& operator++() { _node = _node->_next; return *this; } Ref operator*() { return _node->_data; } bool operator!=(const Self& it) { return _node != it._node; } }; template<class T> class list { typedef ListNode<T> Node; public: typedef ListIterator<T, T&, T*> iterator; typedef ListIterator<T, const T&, const T*> const_iterator; iterator begin() { return iterator(_head->_next); } iterator end() { return iterator(_head); } void empty_init() { _head = new Node(); _head->_next = _head; _head->_prev = _head; } list() { empty_init(); } //左值版本 void push_back(const T& x) { insert(end(), x); } //右值版本 void push_back(T&& x) { insert(end(), move(x)); } iterator insert(iterator pos, const T& x) { Node* cur = pos._node; Node* newnode = new Node(x); Node* prev = cur->_prev; // prev newnode cur prev->_next = newnode; newnode->_prev = prev; newnode->_next = cur; cur->_prev = newnode; return iterator(newnode); } iterator insert(iterator pos, T && x) { Node* cur = pos._node; Node* newnode = new Node(move(x)); Node* prev = cur->_prev; // prev newnode cur prev->_next = newnode; newnode->_prev = prev; newnode->_next = cur; cur->_prev = newnode; return iterator(newnode); } private: Node* _head; }; } // Test.cpp #include"List.h" int main() { bit::list<bit::string> lt; cout << "*************************" << endl; bit::string s1("111111111111111111111"); lt.push_back(s1); cout << "*************************

Read more

C++进阶:(十六)从裸指针到智能指针,C++ 内存管理的 “自动驾驶” 进化之路

C++进阶:(十六)从裸指针到智能指针,C++ 内存管理的 “自动驾驶” 进化之路

目录 前言 一、裸指针的 “血泪史”:为什么我们需要智能指针? 1.1 内存泄漏:最常见的 “噩梦” 1.2 二次释放:致命的 “双重打击” 1.3 野指针:潜伏的 “幽灵” 1.4 异常安全:被忽略的 “隐形杀手” 1.5 智能指针的核心使命 二、智能指针的 “三驾马车”:unique_ptr、shared_ptr、weak_ptr 2.1 unique_ptr:独占所有权的 “独行侠” 2.1.1 unique_ptr 的核心原理

By Ne0inhk
【算法通关指南:数据结构和算法篇】别再用指针写链表了!数组模拟单 / 双向链表,C++ 实战超丝滑

【算法通关指南:数据结构和算法篇】别再用指针写链表了!数组模拟单 / 双向链表,C++ 实战超丝滑

🔥小龙报:个人主页 🎬作者简介:C++研发,嵌入式,机器人方向学习者 ❄️个人专栏:《算法通关指南》 ✨ 永远相信美好的事情即将发生 文章目录 * 前言 * 一、链表的概念 * 1.1 链表的定义 * 1.2 链表的分类 * 二、链表的模拟实现 * 2.1 单链表的模拟实现 * 2.1.1 定义-创建-初始化 * 2.1.2 头插 * 2.1.3 遍历链表 * 2.1.4 按值查找 * 策略一:遍历整个链表 * 策略二:使用哈希表优化 * 2.1.5 在任意位置之后插入元素 * 2.

By Ne0inhk
C++并集查找

C++并集查找

前言 C++图论 C++算法与数据结构 本博文代码打包下载 基本概念 并查集(Union-Find)是一种用于处理动态连通性(直接或间接相连)的数据结构,主要支持两种操作:union 和 find。通过这两个基本操作,可以高效地管理一组元素之间的连通关系。 Find: 查找节点所在有向树的根。 Union: 将两个不同的有向图合并为一棵树。 暴力做法 并集查找处理无向图的数据结构:有向森林,每棵树都是内向树。连通子图都直接或间接指向根,根出度为0,其它节点出度为1。vPar记录各节点的父节点。 Find(u)函数寻找u所在有向树的根(最远祖先): while(-1!= vPar[u]){ u =vPar}return u; 判断u和v是否连通: returnFind(u)==Find(v) 连通: root1 =Find(

By Ne0inhk
【C++:智能指针】没有垃圾回收?智能指针来也!破解C++内存泄漏:智能指针原理、循环引用与线程安全详解

【C++:智能指针】没有垃圾回收?智能指针来也!破解C++内存泄漏:智能指针原理、循环引用与线程安全详解

🎬 个人主页:艾莉丝努力练剑 ❄专栏传送门:《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》 《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》 ⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平 🎬 艾莉丝的简介: 🎬 艾莉丝的C++专栏简介: 文章目录 * C++学习阶段的三个参考文档 * 1 ~> 前言:智能指针的使用场景 * 2 ~> RAII和智能指针的设计思路 * 2.1 理论:RAII * 2.2 最佳实践 * 2.3 实践RAII:核心思想 * 3 ~> C++标准库智能指针的使用 * 3.1 理论

By Ne0inhk