【问题标题】:Cannot initialize non-const reference from convertible type无法从可转换类型初始化非常量引用
【发布时间】:2010-03-25 15:05:02
【问题描述】:

我无法从可转换类型 T2 初始化对类型 T1 的 非常量 引用。但是,我可以使用 const 参考。

long l;
const long long &const_ref = l; // fine
long long &ref = l;             // error: invalid initialization of reference of
                                // type 'long long int&' from expression of type
                                // 'long int'

我遇到的大多数问题都与无法分配给非常量引用的 r 值有关。这不是这里的情况 - 有人可以解释吗?谢谢。

【问题讨论】:

    标签: c++ reference constants type-conversion


    【解决方案1】:

    整数提升会产生右值。 long 可以提升为 long long,然后绑定到 const 引用。就像你已经做过一样:

    typedef long long type;
    const type& x = type(l); // temporary!
    

    相反,如您所知,右值不能绑定到非常量引用。 (毕竟没有实际的long long可以参考。)

    【讨论】:

    • 我找到了我所缺少的:“C++ 标准第 3.10:5 节表明调用不返回引用的函数的结果是一个右值。[type(l) 的结果@ is 一个右值。] 根据第 13.3.3.1.4:3 节,如果需要将非常量引用绑定到右值,则无法形成标准转换序列,隐式对象参数除外。” (在 IBM.com 上找到)
    • @Julien 并不是说​​你认为我是一个书呆子,但你的发现与这里无关,因为l 不是右值。这是一个左值。没有type(l) 出现在您的示例中,并且这样的转换也没有以任何方式隐式进行(在语言级别,这里没有发生整数提升或转换。绑定只是失败,因为没有规则)。此外,type(l) 不是函数调用,而是函数转换表达式。我仍然同意type(l) 是一个右值。
    【解决方案2】:

    long long 的大小不一定等于long,甚至可以使用完全不同的内部表示。因此,您不能将对long 的非常量引用绑定到long long 类型的对象或相反。标准禁止它,您的编译器不允许它是正确的。

    你可以对下面的代码 sn-p 产生同样的疑惑:

    long a = 0; 
    long long b = 0;
    
    a = b; // works!
    
    long *pa = 0;
    long long *pb = pa;
    

    最后一次初始化不起作用。仅仅因为一种类型可以转换为另一种类型,并不意味着复合其中一种的另一种类型可以转换为复合另一种的第三种类型。同样,对于以下情况

    struct A { long i; };
    struct B { long long i; };
    
    A a;
    B b = a; // fail!
    

    在这种情况下,AB 分别复合类型 longlong long,就像 long&long long& 复合这些类型一样。然而,它们不会因为这个事实而相互转换。其他规则恰好适用。

    如果引用是 const,则创建一个具有正确类型的临时对象,然后将引用绑定到该对象。

    【讨论】:

    • 你确定大小和表示有很大关系吗?我也不能用 char 类型的变量初始化有符号或无符号 char 引用,即使其中一个必须与 char 几乎相同。我认为这只是修补 C 类型系统中的一个漏洞(似乎允许指针使用)以提高类型安全性的规则。
    • 我明白你的意思:仅仅因为 A 可以转换为 B 并不意味着 A& 可以转换为 B&。但这不是示例:我将 A 转换为 B&(longlong long &)。
    • @Julien,道理是一样的。仅仅因为您可以将float 转换为int 并不意味着您可以将float 转换为int*
    • @UncleBens,正确。相同的大小和表示不足以使转换成功。在初始化中使用相同的类型/类或派生类或兼容的限定类型就足够了。对于非类类型,这意味着大小和表示是相同的。因此,具有与您在示例中所示相同的大小和/或表示形式是必要的,但根本不够。
    • 无论如何,第 2 行成功:我可以将我的long“转换”为const long long &,所以我觉得问题出在其他地方。
    【解决方案3】:

    我不是标准律师,但我认为这是因为long longlong 更广泛。允许使用 const 引用,因为您不会更改 l 的值。常规引用可能会导致分配对于l 来说太大,因此编译器不会允许这样做。

    【讨论】:

      【解决方案4】:

      让我们假设这是可能的:

       long long &ref = l; 
      

      这意味着稍后在代码中您可以将 ref 引用的值更改为大于 long 类型可以保持但可以保持 long long 的值。实际上,这意味着您覆盖了额外的内存字节,这些字节可由不同的变量使用,结果无法预测。

      【讨论】:

        猜你喜欢
        • 2015-01-26
        • 2013-01-07
        • 2013-10-11
        • 2020-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多