C++ 将 const 引用分配给实例变量(内存问题?)

问题描述 投票:0回答:3

我一直认为引用在功能上与指针相同,它们只是有更友好的语法,以及其他一些细微的差异(引用不能被分配null,它们不能被重新分配)。

但是今天我看到这段代码,我不明白为什么它是正确的:

有一个简单的结构,

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

我认为当

color
超出范围时:当
someFunction
结束时,它就会被销毁。但是
setColor
获取在堆栈上创建的内容的内存地址,并将其存储。但是没有问题,当我访问
Node
_color
时,它始终存在并且具有正确的值。

我在这里缺少什么?

c++ memory-management reference stack instance-variables
3个回答
8
投票

_color = color;
采用
color
的值副本,因此
color
最终超出范围并不重要。

如果成员变量

_color
本身 引用,则会遇到问题。


1
投票
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. 的对象
  3. 参考给它
    setColor
  4. 参数
    color
    现在是
    color
  5. 的引用(别名)
  6. color
    的值复制到
    _color
    (赋值),因为
    _color
    不是引用
  7. color
    被摧毁

1
投票

如果

_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

© www.soinside.com 2019 - 2024. All rights reserved.