使用指针会导致内存堵塞吗?

发布于 2024-12-28 08:01:39 字数 1247 浏览 0 评论 0原文

假设我在 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;

谢谢。

Suppose I have this structures in 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));
    }
}

Will accessing the the values in c ten times require more memory traffic than creating a direct pointer to c and use it? In code terms (assuming legal values):

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();

vs.

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;

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

紙鸢 2025-01-04 08:01:39

可能性不大。不会有什么区别。

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

这是由于名为 Common 的标准编译器优化所致子表达式消除 (CSE)。

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


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

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

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

Chances are no. There will be no difference.

While it is true that dereference chaining will lead to more memory accesses, modern compilers are able to do exactly what you have done. (That is, transform your first example into your second example.)

This is due to a standard compiler optimization called Common Subexpression Elimination (CSE).

The name pretty much says it all. In your first example, a->b->c is the common subexpression that will be optimized out by the compiler. It will be evaluated only once, the result saved, and reused for all the instances it is needed.


There are a number of situations that could prevent a compiler from making such optimizations.

  1. If any relevant variables are declared volatile, then this optimization is not allowed since a volatile variable requires that it be reloaded each time it is used.
  2. If any of the relevant variables are (or potentially) modified, then this optimization is not allowed since it may produce a different result.

As a side-note though, your second example is also more readable since there's dereference chaining.
So if I had to pick which to use, I'd go with the second example anyway.

许久 2025-01-04 08:01:39

在这种情况下,一个好的编译器应该能够消除通用表达式并生成几乎最优的代码。由于您正在访问原始类型,因此 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,因此必须重新评估链来确保。

我几乎将现阶段担心这一点称为过早优化。也就是说,您的第二个示例更具可读性,并且可以帮助编译器在稍后插入任何方法调用时不必进行二次猜测,所以我会这样做。

In this exact case, a good compiler should be able eliminate the common expression and generate pretty much optimal code. Since you're accessing primitive types, a->b->c can be evaluated once and used throughout the method.

The call to C::USize() or access of a non primitive type in "class C" will break this pattern and force the compiler to re-evaluate a->b->c for the next line.

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;

This is because the compiler cannot make 100% sure that a method call/operator does not change a, a.b or b.c, so it has to re-evaluate the chain to make sure.

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.

暮光沉寂 2025-01-04 08:01:39

理论上不会产生任何影响

任何现代优化器都应该转换为完全相同的代码。

Theoretically it will not make a difference.

Any modern optimizer should translate to exactly the same code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文