【问题标题】:Assigning double to const int& vs int to const int&将 double 分配给 const int& 与 int 分配给 const int&
【发布时间】:2013-10-15 22:33:03
【问题描述】:

我试图理解 C++ 中的常量引用,但偶然发现了这个问题:

当我将 double 分配给 const int& 然后更改引用 double 的值时,我的 int 引用的值保持不变。

    double i = 10;
    const int &ref = i;    
    i = 20;

    cout << "i: " << i << endl;      // i = 20
    cout << "&ref: " << ref << endl; // ref = 10

而在分配 int 时,值会发生变化。

    int i = 10;
    const int &ref = i;    
    i = 20;

    cout << "i: " << i << endl;      // i = 20
    cout << "&ref: " << ref << endl; // ref = 20

这种行为的原因是什么?我的猜测是,当分配 double 时,隐式转换为 int 会创建一个新对象,然后分配它的引用,但是我在任何地方都找不到它。

【问题讨论】:

  • =没有赋值,它的初始化/构造。
  • @juanchopanza 我正在使用来自 Cygwin 的 g++
  • @KubaSpatny 抱歉,我看错了作业。忽略我之前的消息。

标签: c++ int constants


【解决方案1】:

尽管看起来像,ref 并不是对i 的引用。

double i = 10;
const int &ref = i;   // ***
i = 20;

int 的引用不能引用double。因此,在标记的行中,发生了从doubleint 的转换,转换的结果是一个临时右值。通常,当它们创建的完整表达式结束时,它们会被销毁。但是 C++ 中有一条规则允许在绑定到 const 的引用时延长临时的生命周期。它被延长直到引用死亡。为此,编译器实际上在后台为其分配了一些内存。

赋值修改了原始对象i,未命名的临时保持不变。

【讨论】:

  • 这种行为的原因是什么?它看起来非常危险且不可预测,所以我认为它一定有什么用处。
  • 这就是我正在寻找的解释 :) 谢谢!
  • @Kylotan 例如,它允许编写v.push_back( SomeClass(42) );,其中v 是某个容器,无需创建MyClass 的命名对象,也无需不必要的副本。
  • @KubaSpatny 没问题。我会粘贴描述这一点的标准中的规范性文本,但我忘记了它到底在哪里,而且已经很晚了:)
【解决方案2】:
double i = 10;
const int &ref = i; 

根据您使用此代码的编译器,原样也可能会产生编译错误。

在引发错误的编译器上,如果将其强制转换为 (int &amp;),您会看到未定义的行为,因为您正在从双精度的位置读取一个 int。 在接受这一行的编译器上,我最好的猜测是它正在创建一个临时变量(一个右值)并分配给 int 引用,并且对原始变量的任何更改都不会反映在引用中。

为了参考工作,请确保源数据类型可以由目标数据类型表示。

【讨论】:

    【解决方案3】:

    只有从两个声明中删除 const 并尝试编译代码 sn-ps,编译器才能为您提供很多帮助:

    double i = 10;
    /*const*/ int &ref = i;    //ERROR - WHY?
    

    这段代码会出现编译错误!为什么?

    但是这段代码:

    int i = 10;
    /*const*/ int &ref = i;   //NO ERROR
    

    可以正常编译。

    如果第一个代码在有const 时编译得很好,为什么现在不编译(当const 不存在时)?幕后发生了什么?

    嗯,原因是,实际上int&amp; 是一个引用类型,它只能引用int 类型的对象,而不是double,所以是@987654329 类型的临时对象@ 是由表达式i(即double)创建的,但临时对象不能绑定到int&amp;,所以它会给出编译错误,但只要你把@987654333 @ 那里,它编译得很好,因为int 类型的临时对象可以绑定到const int&amp;

    第二个代码中没有发生这样的事情——没有创建临时对象。因此,当您将i 设置为20 时,ref 在第二种情况下也会发生变化(因为它指的是i)但在第一种情况下,当您将i 设置为20 时,@ 987654342@ 确实 not 改变,因为 ref 确实 not 不再引用 i - 它而是指临时对象(您 不是强>变化!)。这解释了您的代码 sn-ps 的行为。

    希望对您有所帮助。

    【讨论】:

    • 感谢您指出这一点。我来自 Java,我发现很多事情都以不同的方式完成,但很难全部看到。
    【解决方案4】:

    double 转换为int 时,结果是int 类型的右值。这个临时值绑定到一个常量引用变量,因此临时值的生命周期延长到引用变量的生命周期。更改原来的double 对此没有影响。

    【讨论】:

      【解决方案5】:

      您可以将 int 视为一个类,而 int(double);作为从 double 构造 int 的一种方式,您有一个对该 int 的 const 引用,该 int 是从 double 构造的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-10
        • 2011-09-03
        • 1970-01-01
        相关资源
        最近更新 更多