环境VS2017
构造一个矩阵类
class Matrix {
private:
int** _data; //default value is 0
int lines = 0;
int rows = 0;
public:
Matrix(int li, int ro); //lines=li, rows=ro
Matrix(const Matrix& original); //copy
Matrix(Matrix&& rhs); //move copy
~Matrix();
void init(); //calls cin, linear input
void output(); //calls cout, linear output
Matrix operator+(const Matrix& other);
Matrix operator-(const Matrix& other);
Matrix& operator=(const Matrix& other);
Matrix& operator=(Matrix&& rval); //move assign
};
其中:
Matrix::Matrix(Matrix&& rhs) {
this->lines = rhs.lines;
this->rows = rhs.rows;
this->_data = rhs._data;
rhs._data = nullptr;
}
Matrix Matrix::operator+(const Matrix& other) {
Matrix result(this->lines, this->rows);
for (int li = 0; li < lines; li++) {
for (int ro = 0; ro < rows; ++ro) {
result._data[li][ro] = this->_data[li][ro] + other._data[li][ro];
}
}
return result;
}
Matrix& Matrix::operator=(Matrix&& rhs) {
this->_data = rhs._data;
rhs._data = nullptr;
return *this;
}
语句 A3=A1+A2过程:
A1 成员函数operator+ 被调用,该函数在栈上有一个保存结果的临时变量(名字为result),当计算完毕后,执行 return 语句。
return 语句执行过程是,首先 调用了移动复制构造函数生成临时变量(设名为 Ax)把result 内容夺走,此变量在调用operator+函数的栈中。
return 结束,operator+ 弹栈,result 析构被调用(判断空指针避免read access 错误)。
operator+ 弹栈完成。返回调用函数语句 A3=A1+A2;
现在等号右边是一个名副其实的 “匿名变量”(Ax),毫无疑问此时调用的是 移动赋值而不是 复制构造函数。
移动语义的好处在于节省C++中复制构造函数被过分调用,缺点在于程序员要小心被夺取内容的右值的析构等问题。
有点让我意外的是,result 是有名字的变量,却被当作右值来处理。看来 右值引用不只匹配匿名临时变量,此例发现还匹配函数栈上的局部变量。