为什么我可以使用类型别名声明const引用?

8
我有一个简单的问题:据我所知,我可以声明一个指向某种数据类型或指向常量数据类型的const指针,但只能声明对常量数据类型的引用,而不能声明对数据类型的常数引用;这是因为引用已经是常量,不能被重新绑定到另一个对象。

因此,当我尝试创建const ref to someDataType时,会出现编译时错误。但重要的是,当结合使用typedefusingtype alias时。例如:

#include <iostream>

int main() {

    int i{ 10 };
    //  int& const r1{ i }; // error: ‘const’ qualifiers cannot be applied to ‘int&’. Ok here.
    using rInt = int&; // or typedef int& rInt;
    const rInt r2{ i }; // why const is allowed here?
    ++r2; // this proves that the const is applied to the reference not to the object referred to.

    std::cout << r2 << std::endl; // 11

}

正如您在上面看到的,我可以在引用中添加const,但我认为这在该上下文中是多余的。但是为什么C ++允许使用类型别名而不是直接使用?

在我的编译器上,我得到了Alex24.cpp:8:5: warning: 'const' qualifier on reference type 'rInt' (aka 'int &') has no effect [-Wignored-qualifiers]的警告信息...你有开启警告吗?我猜这与你的问题无关,因为你正在询问为什么允许使用const(即使被忽略)。 - Eljay
@FrançoisAndrieux 为什么我可以通过 rInt 更改对象呢? - Alex24
1
它与 using t_Value = int const; t_Value const value{}; 相同,第二次应用 const 没有效果。但是,您的引用是对可变对象的引用,因此可以使用该引用更改对象。请注意,将 const 添加到 rInt 不会将引用转换为对带有 const 限定符的对象的引用。 - user7860670
1
@Alex24 "但是为什么C++允许使用类型别名而不是直接使用呢?" 我并不确定语言正式禁止这样做。编辑:值得一提的是,在VC++ 14.0中,r1会产生一个警告。 - François Andrieux
3
你可能想要添加“语言律师”标签,因为我认为你想要从标准中获取章节和节。 - Eljay
显示剩余4条评论
2个回答

13

因为规范如此规定:

[dcl.ref]...除非通过typedef名称([dcl.typedef],[temp.param])或decltype-specifier ([dcl.type.simple])引入cv限定符,否则CV限定符的引用无效

这类似于您无法声明引用引用,但可以通过typedef(其中引用合并为一个)来实现:

int i;
int& iref = i;
//int& & irefref = iref; // not OK
using Iref = int&;
Iref& iretypedef = iref; // OK; collapses into int&

CV折叠规则和引用折叠规则一样重要,可以使模板和类型推导可用。


5
这是一种常识性的情况。由于引用无法被重新分配,它们的行为就像是const。在引用声明中添加const并没有增加任何内容,因此T & const是被禁止的[dcl.ref]/1
【引用】除非cv限定符是通过typedef名称或decltype说明符引入的([dcl.typedef],[temp.param]),否则cv限定符是不合规的。
你会注意到,如果引用是typedef名称或decltype说明符,则允许使用。所以如果T是T&,那么const将被忽略。如果不是,它会使通用编程变得更加困难。

不存在“隐式const”,引用也不是const。尝试使用std::is_const_v<int&> - M.M
它们也不像是“const”。如果您尝试为const对象分配值,将会出现错误。该语言甚至不允许尝试重新分配引用。 - M.M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接