【问题标题】:C++ assign const reference to instance variable (memory issues?)C++ 将 const 引用分配给实例变量(内存问题?)
【发布时间】:2015-08-24 05:23:59
【问题描述】:

我一直认为引用在功能上与指针相同,只是语法更友好,还有一些其他细微差别(引用不能分配给 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 指的是相同的内存,因此代码是有效的。
  • 您可以将参数的地址与成员的地址进行比较,发现它们不同,并得出结论它们不是同一个对象。使用指针,您的代码看起来像void setColor(const Color3B* c) { _color = *c; } ... _someNode->setColor(&color);。您是否希望_color 在通话后无效?

标签: c++ memory-management reference stack instance-variables


【解决方案1】:

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

如果成员变量_color本身是一个引用,你就会遇到问题。

【讨论】:

    【解决方案2】:
    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. color 的值复制到_color(赋值),因为_color 不是参考
    5. color 被销毁

    【讨论】:

      【解决方案3】:

      如果_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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多