3

假设我有这个结构c++

class A{
  public:
    B b;
}

class B{
  public:
    C c;
}

class C{
  public:
    double x;
    double y;
    double z;
    double s;
    function Usize(){
      s  = sqrt(pow(x,2) + pow(y,2) + pow(z,2));
    }
}

c与创建指向 c 的直接指针并使用它相比,十次访问这些值需要更多的内存流量吗?用代码术语(假设合法值):

double dx = 2*rand()-1;
double dy = 2*rand()-1;
double dz = 2*rand()-1;

a->b->c.x *= dx;
a->b->c.y *= dy;
a->b->c.z *= dz;

if (a->b->c.x > 10) a->b->c.x -= 10;
else if (a->b->c.x <0) a->b->c.x += 10;
if (a->b->c.y > 10) a->b->c.y -= 10;
else if (a->b->c.y < 0) a->b->c.y += 10;
if (a->b->c.z > 10) a->b->c.z -= 10;
else if (a->b->c.z < 0) a->b->c.z += 10;

a->b->c->Usize();

对比

double dx = 2*rand()-1;
double dy = 2*rand()-1;
double dz = 2*rand()-1;


C* ac = a->b->c
ac.x *= dx;
ac.y *= dy;
ac.z *= dz;

if (ac.x > 10) ac.x -= 10;
else if (ac.x < 0)  ac.x += 10;
if (ac.y > 10) ac.y -= 10;
else if (Ac.y < 0) ac.y += 10;
if (ac.z > 10) ac.z -= 10;
else if (ac.z < 0) ac.z += 10;

谢谢。

4

3 回答 3

11

机会是没有的。不会有任何区别。

虽然取消引用链接确实会导致更多的内存访问,但现代编译器能够完全按照您所做的工作。(也就是说,将您的第一个示例转换为您的第二个示例。)

这是由于称为通用子表达式消除(CSE) 的标准编译器优化。

这个名字几乎说明了一切。在您的第一个示例中,a->b->c是由编译器优化的公共子表达式。它将只被评估一次,结果被保存,并在所有需要它的实例中重复使用。


有许多情况可能会阻止编译器进行此类优化。

  1. 如果声明了任何相关变量volatile,则不允许此优化,因为volatile变量要求每次使用时都重新加载它。
  2. 如果任何相关变量被(或可能)修改,则不允许此优化,因为它可能会产生不同的结果。

不过,作为旁注,您的第二个示例也更具可读性,因为存在取消引用链接。
因此,如果我必须选择使用哪个,无论如何我都会选择第二个示例。

于 2012-01-21T08:35:36.643 回答
2

在这种情况下,一个好的编译器应该能够消除通用表达式并生成非常优化的代码。由于您正在访问原始类型,因此 a->b->c 可以被评估一次并在整个方法中使用。

调用 C::USize() 或访问“类 C”中的非原始类型将打破这种模式并强制编译器为下一行重新评估 a->b->c。

a->b->c.x = 10;
a->b->c.Usize();   // <-- Usize() may change a.b so the next line references another B.
a->b->c.y = 5;

这是因为编译器无法 100% 确定方法调用/操作符不会更改 a、ab 或 bc,因此它必须重新评估链以确保。

I'd almost call worrying about this at this stage premature optimization. That said, your second example is both more readable and helps the compiler not have to second guess in case you insert any method calls later, so I'd go for that.

于 2012-01-21T08:47:18.933 回答
1

理论上它不会有所作为

任何现代优化器都应该翻译成完全相同的代码。

于 2012-01-21T08:34:07.397 回答