类型 && 引用名 = 右值表达式;
例如:
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号
广州松河信息科技有限公司 版权所有