假设我们创建一个Matrix<n, m>
类,该类将nxm个整数存储在成员变量std::array<std::array<int, m>, n> inner;
中。现在有两种添加方法:
[方法1)按值返回(可以使用constexpr
)
template<int n, int m> class Matrix {
...
constexpr Matrix add(const Matrix& that) const {
matrix ret;
for (int y = 0; y < n; y++)
for (int x = 0; x < m; x++)
ret.inner[y][x] = this->inner[y][x] + that.inner[y][x];
return ret;
}
...
}
方法2)返回指针(不可能constexpr
)
template<int n, int m> class Matrix {
...
Matrix *add(const Matrix& that) const {
Matrix *ret = new Matrix();
for (int y = 0; y < n; y++)
for (int x = 0; x < m; x++)
ret->inner[y][x] = this->inner[y][x] + that.inner[y][x];
return ret;
}
...
}
我的程序需要对1000x1000
矩阵(图像)进行算术运算,因此使用方法1我立即得到了stackoverflow。我的程序还适用于需要在编译时计算的较小4x4
矩阵(量子计算中的密度矩阵),因此在这些constexpr
初始化中使用方法2是不可能的。
问题:每个返回Matrix
的方法都需要制作两个版本吗? (一个返回Matrix
,另一个返回Matrix*
)这将是很多重复的代码。这个问题有多普遍?是否有使用堆的替代方法,以便从constexpr
也可以使用方法2?
This answer提到移动语义已经将偏好稍微转移到了[[方法1。但是结果导致堆栈溢出呢?
template<size_t n, size_t m> class Matrix
{
public:
Matrix& operator+=(const Matrix& other)
{
return *this;
}
};
template<size_t n, size_t m>
Matrix<n, m> constexpr operator+(Matrix<n, m> x, Matrix<n, m> const& y)
{
x += y;
return x;
}
template<size_t n, size_t m>
Matrix<n, m>* add(Matrix<n, m> const* x, Matrix<n, m> const* y)
{
Matrix<n, m>* result = new Matrix<n, m>(*x);
*result += *y;
return result;
}
现在,您可以在小型环境中使用大型矩阵,并且可以执行以下操作:现在您可以按值使用矩阵,例如:
Matrix<10, 12> m1, m2; auto m3 = m1 + m2;
您可以动态分配的大型矩阵:
auto pm1 = std::make_unique<Matrix<12, 10>>(); auto pm2 = std::make_unique<Matrix<12, 10>>(); auto pm3 = add(pm1, pm2);
甚至:
auto pm3 = std::make_unique<Matrix<12, 10>>(pm1); *pm3 += *pm2;