我知道将 const 引用变量传递给函数的 const 引用参数不会导致函数参数的类型为“const reference of a const reference of the referee's type”。 const 引用参数的变量名仅被视为 refere 的另一个别名,但受到保护,即该别名不能用于修改 refere。
将引用变量的名称用作引用变量的别名的想法很好地适用于变量,提供了另一层间接性。应用类似的想法似乎没有意义:
- const 引用类型本身被用作其引用者类型的别名,
- const 引用类型 的
typedef
用作其引用者类型 的别名, - 当模板参数为
typename T
时,传递给(或由其推导出)template
参数的 const 引用变量将其类型解释为其 refere 的类型及其函数参数是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"
}
为什么即使对于已经是
int const&
的参数,函数模板也能正常工作? (在示例代码中,它甚至适用于将int const&
变量作为第一个参数并将int
变量作为第二个参数的调用。)它不应该是无效,因为 C++ 不 允许“reference of a reference”?int const&
的typeid
的name()
不应该是int const&
, 而不是int
?如果不是,那么这是否意味着
int const&
是int
的别名;这没有任何意义,因为两者是不同的类型(不是变量名称)?回到变量名,给定:
int num = 8; int const& ref = num; std::cout << typeid(ref).name() << std::endl;
为什么输出是
int
,而不是int const&
?
最佳答案
函数参数是表达式,而不是对象。即使您提供单个对象作为函数参数,它仍然是一个表达式。模板参数推导过程不适用于该对象的声明类型。它不关心它的确切声明类型。它关心的是那个表达式的类型。
C++ 中的表达式从不解释为具有引用类型。每个物理上具有引用类型的表达式总是被解释为非引用类型的左值(或xvalue)。 “引用”部分立即不可逆转地丢弃和遗忘。
标准中是这样写的(5/5)
5 If an expression initially has the type “reference to T” (8.3.2, 8.5.3), the type is adjusted to T prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression.
例如,在您的代码中,rx
被声明为 int const &
。但是,每次您将 rx
用作表达式时,该表达式的结果总是立即从 int const &
调整为 int const
并且是被视为 int const
类型的左值。在“表达式结果”上下文中,语言完全忽略了 rx
是引用这一事实。
人们常说,引用可以看作是现有对象的另一个名称。这正是此处适用的原则。在“表达式结果”上下文中,rx
和 x
之间没有区别(除了 const 限定)。
返回到您的代码,在此调用中
int z = ::min(rx, y);
函数参数分别解释为 int const
和 int
类型的左值。 (即第一个参数并没有真正被视为具有 int const &
类型,这与您的期望相反)。这些是用于模板参数推导的类型。因此,T
被推断为 int
。在这个过程中,任何时候都不可能尝试产生“引用对引用”。
typeid
的工作原理与您观察到的完全相同。 typeid
不会为您提供对象的声明类型。 typeid
的参数在您的案例中是一个表达式。这种形式的 typeid
为您提供了表达式结果的类型,这就是 typeid
无法“看到”引用的原因。 const
部分被丢弃,因为这正是 typeid
的工作方式:顶级 cv-qulifiers 总是被 typeid
丢弃。
关于c++ - const 引用的类型是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20556587/