为什么"const T&"不确定是常量?

Why is `const T&` not sure to be const?

本文关键字:常量 不确定 const 为什么      更新时间:2023-10-16
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);
}

请注意:bconst T&++b可以!

为什么const T&不一定是常量

欢迎使用const和引用折叠。当您有const T&时,引用将应用于Tconst也是如此。你像一样调用g

g<int&>(n);

所以您已经指定Tint&。当我们将一个引用应用于一个左值引用时,这两个引用会塌陷为一个引用,因此int& &就变成了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&将应用于它,并且您可能会因为试图修改常量变量而收到编译器错误。

我知道已经有一个公认的答案是正确的,但只是添加一点,即使在模板领域之外,通常也只是在函数声明中。。。

( const T& ) 

与不同

( const T )

在与第一个匹配的示例中,您有一个const引用。如果您确实想要一个不可修改的常量值,请删除引用,如第二个示例所示。