template<typename T>
void f(T a, const T& b)
{
++a; // ok
++b; // also ok!
}
template<typename T>
void g(T n)
{
f<T>(n, n);
}
int main()
{
int n{};
g<int&>(n);
}
请注意:b
是的const T&
并且++b
是好的!
为什么const T&
不确定是const?
template<typename T>
void f(T a, const T& b)
{
++a; // ok
++b; // also ok!
}
template<typename T>
void g(T n)
{
f<T>(n, n);
}
int main()
{
int n{};
g<int&>(n);
}
请注意:b
是的const T&
并且++b
是好的!
为什么const T&
不确定是const?
欢迎使用 const 和参考折叠。当您拥有const T&
时,引用将应用于T
,const
. 你打电话g
喜欢
g<int&>(n);
所以你已经指定这T
是一个int&
. 当我们对一个左值引用应用一个引用时,这两个引用折叠成一个引用,所以int& &
变成了 just int&
。然后我们从[dcl.ref]/1得到规则,它指出如果你应用const
到一个引用,它会被丢弃,所以int& const
就变成了int&
(注意你实际上不能声明int& const
,它必须来自 typedef 或模板)。这意味着对于
g<int&>(n);
你实际上是在打电话
void f(int& a, int& b)
而且您实际上并没有修改常量。
如果你打电话g
给
g<int>(n);
// or just
g(n);
那么T
将是int
,并且f
会被标记为
void f(int a, const int& b)
由于T
不再是引用,const
并且&
get 应用于它,并且您会收到编译器错误以尝试修改常量变量。
我知道已经有一个公认的答案是正确的,但只是添加一点,即使在模板领域之外并且通常只是在函数声明中......
( const T& )
不一样
( const T )
在与第一个匹配的示例中,您有一个 const 引用。如果您确实想要一个不可修改的 const 值,请删除第二个示例中的引用。