(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)-- 移动构造
下面是自己实现 List 的右值版本的 push_back。注意右值在层层传递的时候属性的变化,要 move 保持其右值属性才能调用移动构造。
// List.h
#include <iostream>
std;
bit {
< >
{
ListNode<T>* _next;
ListNode<T>* _prev;
T _data;
( T& data = ()) :_next(), _prev(), _data(data) {}
(T&& data)
:_next(), _prev(), _data((data)) {}
};
< , , >
{
ListNode<T> Node;
ListIterator<T, Ref, Ptr> Self;
Node* _node;
(Node* node) :_node(node) {}
Self& ++() {
_node = _node->_next;
*;
}
Ref *() { _node->_data; }
!=( Self& it) { _node != it._node; }
};
< >
{
ListNode<T> Node;
:
ListIterator<T, T&, T*> iterator;
ListIterator<T, T&, T*> const_iterator;
{ (_head->_next); }
{ (_head); }
{
_head = ();
_head->_next = _head;
_head->_prev = _head;
}
() { (); }
{ ((), x); }
{ ((), (x)); }
{
Node* cur = pos._node;
Node* newnode = (x);
Node* prev = cur->_prev;
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = cur;
cur->_prev = newnode;
(newnode);
}
{
Node* cur = pos._node;
Node* newnode = ((x));
Node* prev = cur->_prev;
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = cur;
cur->_prev = newnode;
(newnode);
}
:
Node* _head;
};
}
{
bit::list<bit::string> lt;
cout << << endl;
;
lt.(s1);
cout << << endl;
lt.(bit::());
cout << << endl;
lt.();
cout << << endl;
lt.((s1));
cout << << endl;
;
}


