代理类C++优势

C++ Advantage of Proxy Classes

本文关键字:优势 C++ 代理      更新时间:2023-10-16

斯科特·迈耶斯(Scott Meyers)在"有效的现代C++"中说,表达式

Matrix sum = m1 + m2 + m3 + m4

(其中所有对象都有类型Matrix)"如果operator+forMatrix对象返回结果的代理而不是结果本身,则可以更有效地计算。也就是说,两个Matrix对象的operator+将返回代理类(如Sum<Matrix, Matrix>)的对象,而不是Matrix对象。这将对整个初始化表达式进行编码,即类似于Sum<Sum<Sum<Matrix, Matrix>, Matrix>, Matrix>."。

现在,我知道代理类模拟其他一些类的行为并执行隐式连接,但是在这种情况下代理方法如何以及为什么更有效?

此致敬意

考虑到Matrix可能是一个任意大小的矩阵,因此它必须从堆中为其元素分配存储。将两个矩阵相加意味着分配存储并执行逐元素复制。

在上面的表达式中,这意味着为(m1 + m2)分配一次存储,以将其结果添加到m3,第三次将其添加到m4。(移动语义可以降低此成本。

如果添加返回一个代理,该代理仅表示添加,同时保存对要添加的事物的引用,则只为最终分配分配一次。

随着幕后工作的增多,可能会更加懒惰,按需只计算结果矩阵中需要的那些元素。

但是,这些事情始终是一种权衡,您需要评估每种情况下的成本和收益。

为了演示它在代码中的工作方式,我在这里实现了一个示例,它模仿了书中的描述。

如示例中所述,惰性计算发生在矩阵的副本 Ctor(第 30 行)上,实际执行计算。它更有效,因为不会创建临时对象,而是直接就地计算。

我还使用调用研磨在传统的基于 OO 的实现和基于模板表达式的实现之间进行性能比较。

设置:

  • 矩阵大小: (1, 2000)
  • 待评估表达式:mat_a + mat_a + mat_a + mat_b + mat_c;

结果:

模板表达式(成本:618037)

面向对象 + 运算符(成本:944424)