const引用的类型是什么?

时间:2013-12-12 23:48:14

标签: c++ templates types typedef const-reference

我知道将const引用变量传递给函数的const引用参数不会导致函数参数属于“裁判类型的const引用的const引用”。 const引用参数的变量名称仅被视为裁判的另一个别名,但得到了保护,即所述别名不能用于修改裁判。

使用引用变量名称的想法就好像它是裁判变量的别名一样适用于变量,给出了另一层间接。应用类似的想法似乎没有意义:

  • 一个 const引用类型本身就像它是其裁判的类型的别名一样,
  • {{1>} const引用类型被用作其裁判的类型的别名,
  • 传递给typedef参数(或由template参数推导出来的const引用变量,当模板参数为typename T且其函数参数为T const&时,其类型被解释为其裁判的类型

但这似乎发生在以下情况:

#include <typeinfo>
#include <iostream>

template <typename T>
T const& min(T const& a, T const& b) {
    std::cout << typeid(a).name() << std::endl;
    std::cout << typeid(b).name() << std::endl;
    return a < b ? a : b;
}

int main() {
    int x = 6, y = 7;
    int const& rx = x;
    std::cout << typeid(rx).name() << std::endl;           // "int"
    int z = ::min(rx, y);       //output shows both "a" and "b" are of type "int"
    std::cout << z << std::endl;                           // “6”
    typedef int const& icr;
    std::cout << typeid(icr).name() << std::endl;          // "int"
    std::cout << typeid(int const&).name() << std::endl;   // "int"
}
  1. 为什么功能模板即使对于已经int const&的参数也有效? (在示例代码中,它甚至适用于具有int const&变量作为第一个参数并且int变量作为第二个参数的调用。)不应该是无效的,因为C ++不会 允许“引用引用”

  2. typeid的{​​{1}} name() int const&不应该是int const&而不是int

  3. 如果没有,那么这不意味着int const&int的别名;这没有任何意义,因为两者都是不同的类型(不是变量的名称)?

  4. 回到变量名,给出:

    int num = 8;
    int const& ref = num;
    std::cout << typeid(ref).name() << std::endl;
    

    为什么输出int,而不是int const&

2 个答案:

答案 0 :(得分:3)

  1. 因为引用是在类型推导的上下文中折叠的,因此const也是如此。查找参考折叠,已经有很多答案。

  2. 不,因为引用是透明的,你不能看它们;当你命名一个作为参考的变量时,语言总是认为你的意思是裁判。当您引用typeidconst时,它会忽略它。

  3. 避免加粗像变量这样不重要的词语,这会使你的问题难以阅读:)

答案 1 :(得分:2)

函数参数是表达式,而不是对象。即使您提供单个对象作为函数参数,它仍然是一个表达式。模板参数推导过程不适用于该对象的声明类型。它并不关心它的确切声明类型。它关心的是表达式的类型

C ++中的表达式从未被解释为具有引用类型。物理上具有引用类型的每个表达式始终被解释为非引用类型的左值(或 xvalue )。 “参考”部分立即被不可逆转地丢弃并被遗忘。

这就是标准(5/5)中的措辞

  

5 如果表达式最初具有“对T的引用”类型(8.3.2,   8.5.3),在进一步分析之前将类型调整为T.表达式指定由引用表示的对象或函数,   并且表达式是左值或右值,具体取决于   表达

例如,在您的代码rx中声明为int const &。但是,每次使用rx作为表达式时,该表达式的结果始终会立即从int const &调整为int const,并被视为左值 int const类型。在“表达式结果”上下文中,该语言完全忽略了rx是引用的事实。

人们常说,引用可以被认为是现有对象的另一个名称。这正是这里有效的原则。在“表达式结果”上下文中,rxx之间没有区别(除了const限定)。

在此次通话

中返回您的代码
int z = ::min(rx, y);

函数参数分别被解释为int constint类型的左值。 (即,第一个参数并未真正被视为具有int const &类型,与您的预期相反)。这些是用于模板参数推断的类型。因此,T被推断为int。在这个过程中,任何时候都不可能尝试产生“参考参考”。

typeid正如您所观察到的那样完全相同的原因。 typeid未向您提供对象的声明类型。您的案例中typeid的参数是表达式。此表单中的typeid为您提供了表达式结果的类型,这就是typeid无法“看到”引用的原因。 const部分被丢弃,因为这就是typeid的工作方式:typeid始终会丢弃顶级cv-qulifiers。