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

6
我一直认为引用和指针在功能上是相同的,只是语法更友好,并且有一些小差异(例如:引用不能被赋值为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);    
}

我认为当颜色超出范围时,例如在 someFunction 结束时,它就被销毁了。但是 setColor 得到的是栈上创建的某个东西的内存地址,并将其存储起来。但是当我访问 Node 的 _color 时,没有任何问题,它总是存在且具有正确的值。
我错过了什么?

_colorcolor 不是 指向同一块内存,因此代码是有效的。 - iammilind
你可以将参数的地址与成员的地址进行比较,注意到它们不同,并得出它们不是同一个对象的结论。使用指针,你的代码看起来像这样:void setColor(const Color3B* c) { _color = *c; } ... _someNode->setColor(&color);。你会期望在调用后 _color 无效吗? - molbdnilo
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. 将其按引用传递给setColor
  3. 现在,参数colorcolor的引用(别名)
  4. color的值复制到_color中(赋值),因为_color不是引用
  5. 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接