【发布时间】:2020-04-27 13:06:12
【问题描述】:
假设我们创建了一个 Matrix<n, m> 类,它将 nxm 个整数存储在成员变量 std::array<std::array<int, m>, n> inner; 中。现在有两种添加方式:
方法一)按值返回(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。但是由此产生的堆栈溢出呢?
【问题讨论】:
-
不要使用
std::array<std::array<int, m>, n>,使用适当大小的std::vector<int>。 -
不幸的是,这是不可能的。我确实调用了一个外部 dll(数学内核库),它期望矩阵像
std::array一样存储。 -
实际导致溢出的部分不在您发布的代码中。如果
Matrix确实管理动态内存,则不需要动态分配Matrix -
如果你说的是Intel的MKL,它在C接口中使用一维数组,没有C++接口。
-
只有 1000x1000?如果您没有太多线程,或者您使用的是 64 位二进制文件,则只需增加堆栈大小即可。