为什么 `const T&` 不确定是 const?

Why is `const T&` not sure to be 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 和 reference collapsing。当您有 const T& 时,引用将应用于 Tconst 也是如此。你叫g喜欢

g<int&>(n);

所以您指定 Tint&。当我们将引用应用于左值引用时,两个引用合并为一个引用,因此 int& & 变成 int&。然后我们得到来自 [dcl.ref]/1 的规则,它指出如果你将 const 应用于一个引用,它会被丢弃,所以 int& const 就变成 int&(注意你可以' t 实际上声明 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 引用。如果您真的想要一个不可修改的 const 值,请删除第二个示例中的引用。