【问题标题】:Reference with constant modifier使用常量修饰符引用
【发布时间】:2012-12-24 11:42:26
【问题描述】:

FirstOne::

double & val = 66.6;     //illegal
const double & val = 66.6;   //legal

我只是在做一些演示程序,并通过了上述概念,但无法确定上述概念的确切需求。 在第二种情况下 const 到底在做什么?

第二个::

int nVar = 12;
int &rVar = nVar ;//Ok
double &dVar = nVar ;//Error
const double &cdVar = nVar ;//Ok

为什么第三条语句不起作用,而第四条语句起作用?

【问题讨论】:

    标签: c++ reference constants


    【解决方案1】:

    第一个是非法的。您不能将非常量引用绑定到临时对象。

    第二个是合法的。它创建一个临时 double,初始化为 66.6,并使 val 成为对其的 const 引用。

    const 承诺不会通过引用更改值。 C++ 不允许您将非常量引用绑定到临时引用,因为这通常是一个错误。

    【讨论】:

    • 实时编程需要吗?
    • @viku 在回合制编程中需要它。
    • @viku:实时编程需要什么?
    • @DavidSchwartz 上述使用常量引用的概念。
    • 这并不是说执行会更快,因为任何体面的编译器都会忽略副本。例如,考虑一个不可复制的类,例如流。
    【解决方案2】:

    让我告诉你。

    void f(Base*& p) { p = new Base; }
    int main() {
        Derived* d;
        f(d); // Creates temporary Base* and calls f with it
        // Dude, where's my object?
    }
    

    如您所见,这引入了一个令人讨厌的错误。首先,对象被泄露并且无法恢复,因为f 的参数实际上根本没有引用d。其次,即使df中成功变异,也会是错误的类型,违反了类型系统。

    【讨论】:

    • 虽然这是 C++ 不允许您这样做的原因,但对于初学者来说非常难以理解。 (第一行代码的要点是接受一个指针的引用,这样指针就可以指向一个新创建的对象。但是如果指针是临时的,那么代码就会失败,因为调用代码没有填写它的指针。)
    • 我是初学者。你能解释一下你的概念吗?
    • Viku:第一行是一个函数,它接受一个引用,以便它可以指向一个新创建的对象。如果该引用是对临时对象的引用,那么当临时对象被销毁时,新创建的对象将丢失。这是一个非常微妙的错误。 (你可以想象更糟糕的错误。考虑f 是否这样做:p = new OtherClassDerivedFromBase();。如果调用者确实获得了指针,Derived * 将指向不同类的实例!
    【解决方案3】:

    由于 val 是对另一个变量的引用,理论上这就像在旧的 fortran 时代一样,将 1.0 作为引用传递给函数(无论在 fortran 中调用什么方法),您可以将 1.0 更改为别的东西。其他一些使用 1.0 作为常量的代码将使用新值。我会说,不允许这样做是个好主意。

    所以,C++ 标准只允许对您不应该修改的任何内容进行常量引用 - 如果您稍后执行 val += 4.0,您期望什么效果?常数 66.6 变成 70.6?

    编辑:我认为场景是你有一个函数

    void func(double &d)
    {
        d += 4.0;
    }
    

    你不能这样称呼它:

    func(66.6);
    

    所以你试过了:

    double &val = 66.6;
    

    那也没用?

    解决这个问题的正确方法是:

    double val = 66.6;
    
    func(val);    // compiler makes a reference to val that is passed to func. 
    

    【讨论】:

    • 是的,我的意思是如果第一个案例是合法的,那么预期的行为会是什么?
    • @MatsPetersson:我想这将是创建一个其生命周期等于引用生命周期的临时对象,将临时对象初始化为 66.6 并使 val 成为对该临时对象的引用。但 DeadMG 的回答说明了为什么这不是 C++ 规则。
    【解决方案4】:

    double & val = 66.6;

    这不会编译,您不能将引用绑定到临时对象。

    const double & val = 66.6;

    这是有效的,将导致对临时 66.6 的引用。

    我认为没有任何理由将该值声明为引用,将其创建为 const double val = 66.6;,然后如果以后需要将其作为引用传递。

    【讨论】:

      【解决方案5】:

      第二种情况的 const 告诉编译器不要复制右边的值。在您的情况下,这并没有太大区别(编译器可能会生成相同的代码)。

      但在以下情况下,someFunction 的结果不会被复制,而是被分配。如果它发生很多或者返回的对象的副本很昂贵,这将特别有用。

      const double & val = someFunction();
      

      您实际上在做的是扩展堆栈上的值/对象的“生命周期”,而不是复制它。这被称为“临时”。由于创建值/对象的代码不知道您将使用它,因此您必须将其设为 const

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-10
        • 1970-01-01
        • 1970-01-01
        • 2022-06-16
        • 2015-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多