我正在尝试编写一个C++类,用于以特定的方式管理数据。更具体:模拟数学矩阵行为,如矩阵乘法和尽可能少的开销。直观上,我想使用重载运算符以获得更好的可读性,但我总是想知道返回结果矩阵的额外分配。特别是当你考虑一个非常大的矩阵时。
到目前为止,我已经设置好了所有的东西,通过提供维度坐标来分配和正确访问存储的数据。对象被堆分配为指针,以完成一些转换矩阵的花哨工作。到目前为止,添加看起来像这样:
Matrix* Add(Matrix* A, Matrix* B, Matrix* result)
{
[...] //Math here
return result;
}
所以在计算的时候,结果是直接写入result对象的,因为它是通过Pointer访问的。
但是当使用运算符重载时,我的困惑开始增加。我会实现这样的东西(简化,最小的问题):
Matrix* operator+(Matrix& other)
{
Matrix* result = new Matrix;
[...] //Math here
return result;
}
想象一下我们生活在一个完美的世界里,泄漏问题被神奇地解决了,但仍然有一个问题,那就是我没有看到一种方法可以在内部为结果分配内存。如果我已经预先分配了对象,或者我从以前的计算中回收了一个对象,那么分配结果内存不是浪费了计算能力吗?有没有更有效的方法可以解决这个问题,或者可能是以某种我不知道的方式进行了内部优化?
2条答案
按热度按时间mwyxok5s1#
在很大程度上,你担心的问题已经解决了。考虑这个虚拟矩阵和调用
operator+
的例子:我省略了实际的矩阵元素和加法,所以我们可以专注于
return result;
。你担心的是复制。由于复制省略,output of the code是:复制省略经历了一些实质性的变化(在某些情况下从非强制性变为强制性),有关详细信息,请参阅What are copy elision and return value optimization?和https://en.cppreference.com/w/cpp/language/copy_elision。
但是,要在更复杂的表达式(如
matrix a = (a + b) * c + (d + e) * f;
)中获得良好的效率,您应该考虑使用表达式模板(例如https://en.wikipedia.org/wiki/Expression_templates)。这是一种推迟实际计算直到实际需要结果的技术(例如,在示例中,a+b
的结果在数学上不需要临时的,但是通过C++,尽管C++允许从operator+
返回任意自定义类型,不需要容易地计算矩阵)。krugob8w2#
你可以使用
shared_ptr
来代替原始指针,最大的好处是它实现了你正在寻找的魔法,以避免泄漏。也就是说,你最好管理一个Matrix对象,它将内存管理推迟到它的内部。最大的好处是你可以处理不同类型的矩阵(例如稀疏矩阵,正常矩阵等)。另一个好处是你让编译器使用移动语义和其他东西来管理优化,这不像指针那样简单。