【C++】第二十六节—C++11(中) | 右值引用和移动语义(续集)+lambda
Hi,我是云边有个稻草人,C++领域博主与你分享专业知识(*^▽^*)

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

本节总览
接着上节,正文开始——
(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 << "*************************