C++11新特性-右值引用(const引用)
扫描二维码
随时随地手机看文章
const引用
在C++语言中,引用是作为一种高效,安全的传递数据的方式而存在的。除了一般的引用类型,还可以声明const引用。
我们有以下一个Image类。
class Image { public: Image(int w, int h) :width(w), height(h) { data = new char[getSize()]; } int getSize(){ return width * height; } virtual ~(){ if(data != nullptr){ delete data; data = nullptr; width = 0; height = 0; } } private: int width = 0; int height = 0; char* data = nullptr; }
上面只是这个类的雏形,只有构造函数,析构函数和取得数据大小的功能。
接下来添加比较两个Image是否相同的函数。最简单的形式大致如下。
bool isSame(Image& img) { if(width == img.width && height == img.height){ return (memcmp(data,img.data,getSize())==0); } else{ return false; } }
这里使用引用类型的参数,避免了没有必要的拷贝动作。当然我们还可以做得更好:由于比较函数没有必要也不应该对比较对象的内容进行修改,所以还可用下面的形式进行承诺:
bool isSame(const Image& img) { if(width == img.width && height == img.height){ char* in = static_cast
通过在参数前面增加const修饰符,向isSame方法的调用者保证,不会修改img的内容。
右值引用
继续添加将一个Image的一部分merge到另一个Image上的方法。函数的内容大致如下(这里忽略处理的细节):
void merge(Image& img){ //接管img中的数据。 img.height = 0; img.width = 0; img.data = nullptr; }
类似的操作在处理在输入对象时一般有两种处理方式。有时希望只是参照而不破坏输入数据,这时可以使用前面讲到的为参数增加const修饰符的方式来承诺;有时为了提高效率或者其他的原因希望可以接管输入的数据,就像上面代码的状态。这时的行为更像是数据移动。
对于第二种方式,如果仅仅定义一般的引用类型,利用者根本没有办法通过方法声明来确定这个操作是否会接管参数中的数据。这种不确定性会造成很大的麻烦。
解决这个问题的方法就是今天文章的题目--右值引用。代码如下:
void merge(Image&& img){ //接管img中的数据。 img.height = 0; img.width = 0; img.data = nullptr; }
我们将参数声明为右值引用,要求像一个临时变量一样任性地使用数据。使用这个函数的方法如下:
Image img1(100, 100); Image img2(100, 200); img1.merge(std::move(img2));
注意代码中的std::move,这是标准库中提供的方法,它可以将左值显式转换为右值引用类型,从而告诉编译器,可以像右值(临时变量)一样处理它。同时也意味着接下来除了对img2赋值或销毁以外,不再使用它。
C++11通过使用右值引用提供了一种接管数据的标准方法。
作者观点
如果说使用const修饰符可以对外承诺不对参数进行修改的话,那么使用右值引用就是对外要求接管参数数据的权利。