Reputation: 4777
I'm confused about C++ move semantics when used with operator overloading.
For example: (header)
#pragma once
#include <vector>
namespace Mat {
using namespace std;
template <class T = double>
class Matrix {
public:
vector<vector<T>> &data;
size_t Rows;
size_t Cols;
// ctor
Matrix(size_t rows = 1, size_t cols = 1) :
data(*(new vector<vector<T>>(rows, vector<T>(cols)))) {
Rows = rows;
Cols = cols;
}
// copy assignment
Matrix &operator=(const Matrix &m) {
cout << "Copy =" << endl;
delete &data;
Rows = m.Rows;
Cols = m.Cols;
data = *(new vector<vector<T>>(m.data));
return *this;
}
// move assignment
Matrix &operator=(Matrix &&m) {
cout << "Move =" << endl;
Rows = m.Rows;
Cols = m.Cols;
data = m.data;
return *this;
}
// destructor
~Matrix() {
delete &data;
}
// addition
Matrix &operator+(const Matrix &right) {
const auto &left = *this;
auto &result = *(new Matrix<T>(left.Rows, left.Cols));
for (size_t r = 0; r < Rows; r++) {
for (size_t c = 0; c < Cols; c++) {
result.data[r][c] = left.data[r][c] + right.data[r][c];
}
}
return result;
}
};
}
(main/driver)
int _tmain(int argc, _TCHAR* argv []) {
Mat::Matrix<double> mat1(3,3);
Mat::Matrix<double> mat2(3, 3);
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(1, 6);
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++) {
mat1.data[r][c] = distribution(generator);
mat2.data[r][c] = distribution(generator);
}
}
Mat::Matrix<double> mat3;
mat3 = mat1 + mat2;
}
When I execute this code. It indicates that "mat3 = mat1 + mat2" is using the copy assignment operator. I expected (and wanted) it to use the move assignment operator. I'm using VS2013.
Can someone explain why this is happening and how I can get the desired move semantics? Thanks
Upvotes: 1
Views: 90
Reputation: 76240
Your operator+
not only is leaking memory, but is also returning a Mat::Matrix
by reference. Therefore the expression mat1 + mat2
can only bind to:
Matrix &operator=(const Matrix&);
What you want to do is to return a Matrix
by value, instead. Finally, I see you are using new
all over the place. You don't need dynamic allocation, especially with std::vector
.
Upvotes: 1
Reputation: 32490
Among a bunch of other issues, your operator+()
is returning a non-const
l-value reference, not a temporary r-value ... thus it's going to bind to the const
l-value reference in the copy assignment operator.
Upvotes: 0