5

来自 Scott Meyers 的 Effective C++:

template<typename T, std::size_t n>
class SquareMatrix: private SquareMatrixBase<T> {

public:

    SquareMatrix( ) 
     : SquareMatrixBase<T>(n, 0), 
       pData(new T[n*n]) 
    {
         this->setDataPtr(pData.get()); 
    } 

        ...
private:

    boost::scoped_array<T> pData;
};

无论数据存储在哪里,从膨胀的角度来看,关键结果是现在 SquareMatrix 的许多(可能是全部)成员函数可以是对基类版本的简单内联调用,这些版本与所有其他持有相同类型的矩阵的矩阵共享数据,不管它们的大小。同时,不同大小的 SquareMatrix 对象是不同的类型,因此即使 SquareMatrix<double, 5> 和 SquareMatrix<double, 1 0> 对象在 SquareMatrixBase<double> 中使用相同的成员函数,也不可能将 SquareMatrix<double, 5> 对象传递给需要 SquareMatrix<double, 1 0> 的函数。不错,不是吗?

不错,是的,但不是免费的。与将大小作为函数参数传递或存储在对象中的共享版本相比,硬连线到其中的矩阵大小的 invert 版本可能会生成更好的代码。例如,在特定于大小的版本中,大小将是编译时常量,因此有资格进行诸如常量传播之类的优化,包括将它们作为立即操作数折叠到生成的指令中。这不能在与大小无关的版本中完成。

在上一段的上述描述中,它被提及为“因此有资格进行诸如常量传播之类的优化,包括将它们作为直接操作数折叠到生成的指令中”。这个说法是什么意思?请要求解释这一点。

谢谢!

4

2 回答 2

10

常量传播是留给编译器的一个非常简单(原则上)的优化。

size_t radius = 5;
size_t diameter = 2*radius;
float perimeter = diameter * 3.1416f;

这将由编译器通过传播常量来减少:

  • 注意 的值radius是已知的
  • 执行计算2*radius(这是常量折叠)
  • 因此的值diameter是已知的
  • 执行计算diameter * 3.1416f
  • 因此的值perimeter是已知的

因此,该程序等价于:

size_t radius = 5;
size_t diameter = 10;
float perimeter = 31.416f;

请注意,还有许多其他形式的优化,例如,如果现在不再需要 和 ,我们可以删除它们并只radius保留.diameterperimeter

于 2011-02-08T15:41:19.447 回答
0

如果您有原始代码,例如:

a:=3;
b:=4;
b+=1;
b+=2;
a:=a+b;

然后编译器可以将语句优化为:

b==7;
a==10;

这就是所谓的常量传播和常量折叠。

于 2015-05-31T03:49:47.577 回答