c++11 右值引用

右值引用是一种复合类型,跟C++的传统引用很类似。为更准确地区分两种类型,我们把传统的C++引用称为 左值引用 。而使用“引用”这一术语时,我们的意思同时包含两种引用:左值引用和右值引用。
右值引用的行为跟左值引用类似,不同之处在于:右值引用可以绑定到临时量(右值),而(非const的)左值引用却不能绑定到右值。 
究竟为何要使用右值引用?

右值引用和左值引用结合起来恰能方便地实现转移语义。右值引用还可以用于实现完美转发,这是C++里面到现在都没有解决的一个问题。从一般程序员的角度来看,使用右值引用,我们得到的将是更加通用,性能也更高的库

template <class T> swap(T& a, T& b)
{
    T tmp(a);   // now we have two copies of a
    a = b;      // now we have two copies of b
    b = tmp;    // now we have two copies of tmp (aka a)
}

拷贝的开销可以很大。举例来说,对于std::vector,像v2=v1这样的赋值通常包含一次函数调用,一次内存分配和一个循环。当我们确实需要一个vector的两份拷贝时,这当然是可接受的,然而很多情况下我们并不需要:我们常常将一个vector从一个地方复制到另一个地方,接着便覆写了旧的版本

但我们并不想拥有a或b的任何拷贝,而只是想交换他们

template <class T> swap(T& a, T& b)
{
    T tmp(std::move(a));
    a = std::move(b);   
    b = std::move(tmp);
}

move()函数的实现在<type_trait>头文件中
template <class _Tp>
inline typename remove_reference<_Tp>::type&& move(_Tp&& __t) { typedef typename remove_reference<_Tp>::type _Up; return static_cast<_Up&&>(__t);}
move函数完成的工作实际上微乎其微。它所做的就是接受一个左值或右值参数,然后将它作为右值返回而不引发拷贝构造:

C++11引入了两个新的特殊成员函数:“移动”构造函数和“移动”赋值重载函数。
C::C(C&& other); 这个构造函数不应该申请新的资源,相当于auto_ptr的资源转移
“移动”等号重载函数如下:
C& C::operator=(C&& other);//C++11 move assignment operator.
“移动"赋值重载函数和拷贝构造函数有一点类似,除了在执行赋值前,要把自己的资源释放掉这一


#include<iostream>
#include<algorithm>

template<typename T>
class stack
{
 T *data;
 int size;
 int used;
 T *Copy(const T *src,size_t srcsize,size_t destsize);
public:
 stack(){data =new T[8];size=8;used=0;}
 stack(int d);
 stack(const stack&);
 stack(stack &&);
 stack &operator=(const stack &);
 stack &operator=(stack &&);
 ~stack(){if(data!=NULL)delete data;}

 void push(T d);
 void pop();
 T &top();
 inline size_t count();
 friend ostream &operator<<(ostream &os,stack<T> &s);
};

template<typename T>
stack<T>::stack(int d)
{
 data=new T[d];
 size=d;
 used=0;
}

template<typename T>
stack<T>::stack(const stack<T> &s):data(Copy(s.data,s.size,s.size)),size(s.size),used(s.used)
{
}

template<typename T>
T *stack<T>::Copy(const T *src,size_t srcsize,size_t destsize)
{
 //assert(destsize>=srcsize);
 T *dest=new T[destsize];
 try
 {
  copy(src,src+srcsize,dest);
 }
 catch(...)
 {
  delete []dest;
  throw;
 }
 return dest;
}

template<typename T>
stack<T>::stack(stack<T> &&s):data(s.data),size(s.size),used(s.used)
{
 cout<<"cop stack<T> &&s ";
 s.data=nullptr;
 s.size=0;
 s.used=0;
}

template<typename T>
stack<T> &stack<T>::operator=(const stack<T> &s)
{
 if(*this!=s)
 {
  if(data!=NULL)
   delete data;
  data=Copy(s.data,s.size,s.size);
  size=s.size;
  used=s.used;
 }
 return *this;
}

template<typename T>
stack<T> &stack<T>::operator=(stack<T> &&s)
{
 cout<<"stack<T> &&s";
 if(*this!=s)
 {
  data=s.data;
  size=s.size;
  used=s.used;
  s.data=nullptr;
  s.size=0;
  s.used=0;
 }
 return *this;
}

template<typename T>
void stack<T>::push(T d)
{
 if(used==size)
 {
  size_t nsize=2*size;
  T *dest=Copy(data,size,nsize);
  delete data;
  data=dest;
  size=nsize;
 }
 data[used++]=d;
}

template<typename T>
void stack<T>::pop()
{
 if(used==0)
  throw "pop error";
 else
  --used;
}

template<typename T>
T &stack<T>::top()
{
 if(used==0)
  throw "top error";
 else
  return data[used-1];
}

template<typename T>
size_t stack<T>::count()
{
 return used;
}

template<typename T>
ostream &operator<<(ostream &os,stack<T> &p)
{
 for(int i=p.used;i>=0;--i)
  os<<p.top();
 return os;
}
int main()
{
 stack<int> s;
 for(int i=10;i>=0;--i)
  s.push(i);
 //cout<<s;
 stack<int> s1(static_cast<stack<int>&&>(s));
 stack<int> s2=static_cast<stack<int>&&>(s1);
 //stack<int> &&s3=s;
 cout<<"s\n";
 for(int i=s.count();i>0;--i)
 {
  cout<<s.top();
  s.pop();
 }
 cout<<"s1\n";
 for(int i=s1.count();i>0;--i)
 {
  cout<<s1.top();
  s1.pop();
 }
 cout<<"s2\n";
 for(int i=s2.count();i>0;--i)
 {
  cout<<s2.top();
  s2.pop();
 }
} 
  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值