类型 && 引用名 = 右值表达式;
例如:class A{}; A & rl = A(); //错误,无名临时变量 A() 是右值,因此不能初始化左值引用 r1 A && r2 = A(); //正确,因 r2 是右值引用
#include <iostream> #include <string> #include <cstring> using namespace std; class String { public: char* str; String() : str(new char[1]) { str[0] = 0; } String(const char* s) { str = new char[strlen(s) + 1]; strcpy(str, s); } String(const String & s) {//复制构造函数 cout << "copy constructor called" << endl; str = new char[strlen(s.str) + 1]; strcpy(str, s.str); } String & operator = (const String & s) {//复制赋值号 cout << "copy operator = called" << endl; if (str != s.str) { delete[] str; str = new char[strlen(s.str) + 1]; strcpy(str, s.str); } return *this; } String(String && s) : str(s.str) { //移动构造函数 cout << "move constructor called" << endl; s.str = new char[1]; s.str[0] = 0; } String & operator = (String && s) { //移动赋值号 cout << "move operator = called" << endl; if (str != s.str) { str = s.str; s.str = new char[1]; s.str[0] = 0; } return *this; } ~String() { delete[] str; } }; template <class T> void MoveSwap(T & a, T & b) { T tmp(move(a)); //std::move(a) 为右值,这里会调用移动构造函数 a = move(b); //move(b) 为右值,因此这里会调用移动赋值号 b = move(tmp); //move(tmp) 为右值,因此这里会调用移动赋值号 } int main() { String s; s = String("this"); //调用移动赋值号 cout << "* * * *" << endl; cout << s.str << endl; String s1 = "hello", s2 = "world"; MoveSwap(s1, s2); //调用一次移动构造函数和两次移动赋值号 cout << s2.str << endl; return 0; }程序的输出结果如下:
String("this")
是右值,因此在定义了移动赋值号的情况下,会导致移动赋值号被调用。移动赋值号使得 s 的内容和 String("this") 一致,然而却不用执行深复制操作,因而效率比复制赋值号高。template <class T> void Swap(T & a, T & b) { T tmp(a); //调用复制构造函数 a=b; //调用复制赋值号 b=tmp; //调用复制赋值号 }Swap 函数执行期间会调用一次复制构造函数,两次复制赋值号,即一共会进行三次深复制操作。而利用右值引用,使用 MoveSwap,则可以在无须进行深复制的情况下达到相同的目的,从而提高了程序的运行效率。
Copyright © 广州京杭网络科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州京杭网络科技有限公司 版权所有