2

我知道将 const 引用变量传递给函数的 const 引用参数不会导致函数参数属于“裁判类型的 const 引用的 const 引用”类型。const 引用参数的变量名仅被视为裁判的另一个别名,但以不能使用该别名来修改裁判的保护为荣。

将引用变量的名称用作裁判变量的别名的想法很好地适用于variables,从而提供了另一层间接性。应用类似的想法似乎没有意义:

  • const 引用类型本身被用作其裁判类型的别名,
  • const 引用类型typedef的 a被用作其裁判类型的别名,
  • 当模板参数为且其函数参数为时,传递给(或由其推导)template参数的 const 引用变量将其类型解释为其裁判的类型。typename TT 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. 不应该是,而不是typeidname()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&

4

2 回答 2

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

  2. 不,因为引用是透明的,你不能看它们;当您将变量命名为引用时,该语言始终认为您指的是裁判。当您typeid引用或const忽略它时。

  3. 避免将不重要的单词加粗,例如variable,这会使您的问题难以阅读:)

于 2013-12-12T23:55:33.197 回答
3

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

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

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

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

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

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

在此调用中返回您的代码

int z = ::min(rx, y);

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

typeid出于完全相同的原因,正如您所观察到的那样工作。typeid没有给你声明的对象类型。在您的情况下,参数typeid是一个表达式typeid这种形式为您提供了表达式结果的类型,这就是为什么typeid不能“看到”引用。该const部分被丢弃,因为这就是typeid工作原理:顶级 cv-qulifiers 总是被typeid.

于 2013-12-13T00:05:41.323 回答