我正在尝试编写一个矩阵计算器,并遇到了一个难题。如果我有A = B*C
,则使用我的重载B*C
评估operator*(const Matrix&)
,其中我需要一些临时对象来进行计算。这很好用。但是一旦我遇到更复杂的东西,我需要更多的临时对象,显然我不想手工做/有混合。
说我想评估:
Matrix A = B*C + D*E*F + G*H;
然后运算符优先级告诉我,*
将首先被评估。所以:
Step 1) B*C -> t1
Step 2) D*E -> t2
Step 3) t2*F-> t3
Step 4) G*H -> t4
Step 5) t1+t2 -> t5
Step 6) t5+t4 -> t6
Step 7) A=t6
这是确切的顺序吗?或者订单是否具有确定性?我的想法是创建一个链表,我将检查我的+和*,如果正在计算的对象(例如t2 * F)是临时的,那么我可以删除它们/适当插入。
答案 0 :(得分:2)
Expression templates可以解决这个问题。例如
Matrix M = 2*(A+B) + C;
通常会为A+B
,2*(A+B)
,2*(A+B) + C
创建3个临时对象。因此,当Matrix
对象是重量级时,这可能会效率低下。
表达式模板是一种模板元编程技术,其中运算符被实现为使得它们返回表示整个表达式的对象,但仅在结束时计算表达式。
所以2*(A+B) + C
会产生类似
sum<multiple<float, sum<Matrix, Matrix>>, Matrix>
能够在不分配中间矩阵的情况下计算M
。 (在这种情况下,通过分量加法和乘以常数)。该对象本身是在零运行时开销时生成的。
因为这很复杂,所以最好使用线性代数库,例如Eigen。
答案 1 :(得分:0)
运算符优先级不告诉您将评估哪些订单。它会告诉您每个运算符的操作数。
评估顺序的唯一保证是必须在操作员操作之前评估操作员的操作数。
要查看更简单的示例2 + 3 * 4
,优先级表示添加到2
的内容为3 * 4
,而不是3
。
在您的示例B*C + D*E*F + G*H
中,唯一的保证是:
G*H
之前评估+
在第一个B*C
+
在D*E*F
+
+
+
D*E*F
内,第一个*
在第二个*
之前进行评估。可能的排序可能是:
(1) D*E
(2) G*H
(3) B*C
(4) 1*F
(5) 3+4
(6) 5+2
另请注意,如果B
,C
等需要自行评估,那么这些评估也不会有任何相对排序。
答案 2 :(得分:-1)
我的想法是创建一个链接列表,我将检查我的+和*, 如果正在计算的对象(例如t2 * F)是临时的, 然后我可以删除它们/插入适当的。
鸵鸟政策。
这绝对没有意义,只有其他问题。很棒的时候。
编译器可以为您处理所有事情,您可以放心地依赖它。 C ++不是汇编程序级别。只返回临时的基于堆栈的对象(没有指针或任何东西)。计算的中间结果将自行清理。
Matrix operator+(const Matrix&) {...}
Matrix operator*(const Matrix&) {...}
并且每个这样的函数都有一个临时对象insde to calcualte,然后返回 这就是你需要的一切。