当对象很大时返回一个指针或值
Posted
技术标签:
【中文标题】当对象很大时返回一个指针或值【英文标题】:Return a pointer or value when objects are large 【发布时间】: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 我会立即得到一个 ***。我的程序还适用于需要在编译时计算的小型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 位二进制文件,则只需增加堆栈大小即可。
【参考方案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>
std::unique_ptr<Matrix<n, m>> add(Matrix<n, m> const* x, Matrix<n, m> const* y)
auto result = std::make_unique<n, m>(*x);
*result += *y;
return std::unique_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.get(), pm2.get());
甚至:
auto pm3 = std::make_unique<Matrix<12, 10>>(pm1);
*pm3 += *pm2;
【讨论】:
我想你忘记了operator+=
中的实际添加。也许至少放一个占位符评论。
@FrançoisAndrieux 它在课堂上......承认,我没有在里面添加任何东西,但为了演示就足够了。以上是关于当对象很大时返回一个指针或值的主要内容,如果未能解决你的问题,请参考以下文章
函数可以返回一个局部对象,而不能返回一个局部对象的引用(指针):
当键或值很大时,为什么redis hash会从ziplist转换为hashtable?