2015-06-09 161 views
0

我一直認爲引用在功能上與指針相同,它們只是有一個更友好的語法,和其他一些小的差異(引用不能分配給null,他們不能被重新分配)。今天C++分配常量引用實例變量(內存問題?)

但我看到這個代碼,我不明白爲什麼它是正確的:

有簡單的結構,Color3B。我們這樣創建一個堆棧:

Color3B color(255,0,0); 

還有一個類,它的一個實例變量是Color3B類型。

class Node{ 

private: 
    Color3B _color; 
public: 
    void setColor(const Color3B& color){ 
     _color = color; 
    } 
}; 

用法:

void someFunction(){ 
    Color3B color(255,0,0); 
    _someNode->setColor(color);  
} 

我認爲,當它超出範圍的顏色被破壞:當someFunction結束。但是setColor會獲得在堆棧上創建的內存地址並將其存儲。但是沒有任何問題,當我訪問Node的_color時,它總是存在並且具有正確的值。

我在這裏錯過了什麼?

+0

'_color'和'color'是**不**代表相同的內存,因此代碼是有效的。 – iammilind

+0

您可以比較參數的地址和成員的地址,注意到它們不同,並得出結論:它們不是同一個對象。使用指針你的代碼看起來像'void setColor(const Color3B * c){_color = * c; } ... _someNode-> setColor(&color);'。你會期望'_color'在通話後無效嗎? – molbdnilo

回答

3

_color = color;需要color的值副本,因此color最終超出範圍並不重要。

如果成員變量_color本身的引用,您會遇到問題。

0
void someFunction(){ 
    Color3B color(255,0,0); // (1) 
    _someNode->setColor(color);// (2) 
}        // (5) 


void setColor(const Color3B& color){ // (2)(3) 
    _color = color;     // (4) 
}          

讓我們看看會發生什麼位置:

  1. 創建一個名爲color對象
  2. 給它參考setColor
  3. 參數color現在的color
  4. 的引用(別名)
  5. color的值複製爲_color(賦值),因爲_color不是引用
  6. color被破壞
0

,你認爲應該發生,如果_color是一個參考,會發生錯誤。

class Node{ 

private: 
    const Color3B& _color; 
public: 
    void setColor(const Color3B& color){ 
     _color = color; 
    } 
}; 

此代碼會產生您期望的錯誤。現在,您實際上會將堆棧中的顏色地址保存到Node中,並且在someFunction()的末尾將會銷燬該地址。但是你不這樣做。您的Node有其自己的Color3B對象,而不是對它的引用。因此代碼_color = color實際上會執行從someFunction()中的顏色到Node對象中的顏色的副本。現在,即使原始顏色被破壞,Node中的一個仍然存在。

如果你用指針寫setColor(),相當於你的代碼是:

void setColor(const Color3B* color){ 
    _color = *color; 
} 

因爲引用不是一個變量,但一個別名的地址。所以上面代碼中的color(如果它是一個引用)代表它的值,而不是地址。要得到地址,你必須寫&color