完美转发
关于右值引用与移动构造请看这里添加链接描述
- 为什么要有完美转发 -> 上一次在讲右值引用时我们说到,右值引用虽然引用的是右值,但是它本身是一个左值,如果这样的话,使用这个值再次向下传递时就可能传递到参数是左值的而不是右值的函数中去,就可能导致本该使用移动构造的函数确实用了拷贝构造,降低了效率。
eg:
template<class T>
struct ListNode
{
ListNode* _next = nullptr;
ListNode* _prev = nullptr;
T _data;
};
template<class T>
class List
{
typedef ListNode<T> Node;
public:
List()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
///
void PushBack(T&& x)
{
//Insert(_head, x);
Insert(_head, std::forward<T>(x));
}
void PushFront(T&& x)
{
//Insert(_head->_next, x);
Insert(_head->_next, std::forward<T>(x));
}
void Insert(Node* pos, T&& x)
{
Node* prev = pos->_prev;
Node* newnode = new Node;
newnode->_data = std::forward<T>(x); // 关键位置
// prev newnode pos
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = pos;
pos->_prev = newnode;
}
private:
Node* _head;
};
int main()
{
List<bit::string> lt;
lt.PushBack("1111");
lt.PushFront("2222");
return 0;
}
因为这里我没有写左值引用的Insert,这里如果没有进行完美转发的话,PushBack和PushFront就会调用左值的Insert,从而会进行深拷贝,这样的效率并不是很高。
- 这里使用一个forward(args),就可以保证args的左右值属性保持不变,从而可以使用相应的移动构造或者完美转发,提升效率。