2015-06-09 64 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