【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++、Java 语法与细节(硬核实操版):看完就能写、跑、解释

精通 C、C++、Java 语法与细节(硬核实操版):看完就能写、跑、解释 概述 * 目标:构建跨 C、C++、Java 的统一认知框架,从语法细节到底层机理(ABI、对象模型、JVM、GC、RAII),保证“写得出、跑得通、讲得明白”。 * 方法:每节包含最小可运行模板、编译命令、常见坑、口决与原理说明。 * 读者:需要在系统开发、服务端开发、高性能场景中跨语言协作的工程师。 简介与项目背景 * C 定位嵌入式/系统库与极致性能;C++ 横跨系统/应用/游戏引擎;Java 主导企业级服务与平台。 * 跨语言合作频繁,统一语义与资源管理认知能显著降低联调与性能回归成本。 名词解释 * ABI:二进制接口约定,

By Ne0inhk
C++ 继承入门(下):友元、静态成员与菱形继承的底层逻辑

C++ 继承入门(下):友元、静态成员与菱形继承的底层逻辑

🔥小叶-duck:个人主页 ❄️个人专栏:《Data-Structure-Learning》 《C++入门到进阶&自我学习过程记录》《算法题讲解指南》--从优选到贪心 ✨未择之路,不须回头 已择之路,纵是荆棘遍野,亦作花海遨游 目录 前言 一. 友元 —— 友元关系不可继承   1、错误版本   2、正确版本 二. 静态成员 —— 继承体系中静态成员的共享性 三. 多继承及菱形继承问题:本质特点与解决方案   1、单继承与多继承模型   2、菱形继承:虚继承解决“数据冗余”与“二义性”     2.1 菱形继承出现的坑(解决二义性问题)     2.2 虚继承:彻底解决菱形继承问题     3、多继承中指针偏移问题 友元,静态成员,

By Ne0inhk
【C++】 —— 笔试刷题day_28

【C++】 —— 笔试刷题day_28

一、游游的重组偶数 题目解析 这道题,有q组数据,每一次输入一个正整数x,让我们将这个数进行重排,变成一个偶数,然后返回(如果x本身就是一个偶数那可以直接返回x); 如果不存在合法解,就是x通过重排后,无法变成一个偶数,就输出-1; 算法思路 这道题,总体来说还是比较简单的; 对于正整数x,我们可以把它当作一个字符串进行输入;(如果按照整数输入,我们还要将这个数x的每一位变换成对应数组) 我们知道,如果一个数是偶数,那最低位一定是一个偶数,这样我们只需判断字符串的最后一位即可知道这个数是否是偶数;如果这个数是偶数,那就直接输出即可;如果最后一位不是偶数,那就从第一位开始向后找,找到一位是偶数,然后把它交换到最后一位;然后输出即可;如果遍历完这个字符串,还没找到一位是偶数的,那就表示这个数x通过重拍无法变成偶数,输出-1即可。 题目解析 #include<iostream>usingnamespace std; string func(){ string str; cin >>

By Ne0inhk

STL转STEP:让3D打印模型轻松走进工程设计世界

STL转STEP:让3D打印模型轻松走进工程设计世界 【免费下载链接】stltostpConvert stl files to STEP brep files 项目地址: https://gitcode.com/gh_mirrors/st/stltostp 你是否曾经遇到过这样的场景:精心设计的3D打印模型完成得相当完美,但当你想把它导入到专业的CAD软件中进行进一步优化或加工时,却发现STL格式根本不被识别?这种挫折感我完全理解,但好消息是,STL转STEP转换正是解决这个问题的金钥匙。 在现代三维设计和制造领域,STL格式虽然适合3D打印,但在工程设计领域却存在诸多限制。当你需要将模型导入到专业CAD软件(如SolidWorks、CATIA等)进行数控加工或装配分析时,STEP格式才是真正的"通行证"。 为什么你需要掌握STL转STEP 想象一下,STL格式就像是给3D打印机看的"说明书",而STEP格式则是给所有工程设计软件都能读懂的"通用语言"。通过STL转STEP转换,你可以实现: * 在不同CAD软件之间无缝交换3D模型数据 * 为数控加工设备提供标准化的

By Ne0inhk