2012-01-21 19 views
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; 

感謝。

+1

你的代碼是錯誤的,這使得很難知道你在問什麼。類成員聲明應該是'B * b'還是'C * c',或者訪問是否應該是'a.b.c.x'等等? – TonyK

回答

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·B或b.c,所以它必須重新評估鏈以確保。

在這個階段,我幾乎不會爲此擔心這個過早的優化。也就是說,你的第二個例子更具可讀性,並且可以幫助編譯器在以後插入任何方法調用時不必再次猜測,所以我會爲此付出努力。

+0

我沒有downvote,但我不跟着你。一個方法調用如何防止優化?如果'A'包含'B'包含'C'並不重要,該方法仍然會執行相同的操作。 –

+0

添加了更具描述性的代碼片段。 –

+0

我還是不明白。 「C類」怎麼知道它是由'B類'包含的?如果是這樣,'C :: Usize()'怎麼會知道'B'的哪個實例要修改? –

1

理論上它不會有區別

任何現代優化器應該轉換成完全相同的代碼。

+0

更正確的說法是_theoretically_它應該有所作爲,但是由於現代編譯器的原因,在實踐中沒有區別。 –

+0

@PaulManta好吧,我的意思是*理論上*所有優化器應該能夠生成相同的代碼:)。 –

11

可能是沒有。沒有區別。

雖然解引用鏈接會導致更多的內存訪問,但現代編譯器能夠完成您完成的工作。 (即,將第一個示例轉換爲第二個示例。)

這是由於稱爲Common Subexpression Elimination(CSE)的標準編譯器優化。

這個名字幾乎說明了一切。在你的第一個例子中,a->b->c是將由編譯器優化的常見子表達式。它只會被評估一次,結果被保存,並被重新用於所有需要的實例。


有一些情況可能會阻止編譯器進行優化。

  1. 如果任何相關變量的聲明volatile,那麼這個優化是不允許的,因爲一個volatile變量需要將其每次使用時重新加載。
  2. 如果任何相關變量(或可能)被修改,則不允許此優化,因爲它可能會產生不同的結果。

作爲一個側面說明,雖然,你的第二個例子也更易讀,因爲有反引用鏈接。
因此,如果我不得不選擇使用哪一個,那麼無論如何我都會使用第二個示例。

相關問題