让我们考虑以下代码段
void Test()
{
int x = 0;
int& rx = x;
int* px = &x;
auto apx = px; // deduced type is int*
auto arx = rx; // deduced type is int
}
可以从指针类型中得出类比,期望推导出的arx
类型为int&
,但事实上它是int
。
标准中的规则是什么?它背后的原因是什么? 有时我会被这样的情况抓住:
const BigClass& GetBigClass();
...
auto ref_bigclass = GetBigClass(); // unexpected copy is performed
答案 0 :(得分:12)
使用auto&
:
auto& ref_bigclass = GetBigClass();
引用应该是透明的:对它们的任何操作都发生在它们引用的对象上,没有办法“获取”引用本身。
UPD:这在7.1.6.4/6中有所介绍:
一旦根据8.3确定了declarator-id的类型,使用declarator-id的声明变量的类型是使用模板参数推导规则从其初始化程序的类型确定的。
模板参数推导在14.8.2.1/3中定义:
如果模板参数类型P是引用类型,则P引用的类型用于类型推导。
P.S。请注意,decltype
的情况不同:decltype(rx)
会产生int&
类型(7.1.6.2/4)。
答案 1 :(得分:8)
考虑它的最简单方法是将其与模板参数推导进行比较。
假设:
template<typename T>
void deduce(T) { }
如果你打电话:
deduce(px);
然后模板参数T
将推断为int*
,如果您致电
deduce(rx);
然后T
将推断为int
,而不是int&
使用auto
时会得到相同的类型。
可以从指针类型中得出类比,期望推导出的
arx
类型为int&
你必须有一个相当混乱的C ++语言模型来进行类比。仅仅因为它们以语法相似的方式声明,因为带有类型和修饰符的Type@
不会使它们以相同的方式工作。指针是一个值,一个对象,它可以被复制并通过赋值改变其值。引用不是对象,它是对某个对象的引用。无法复制引用(复制它复制引用对象)或更改引用(分配引用会改变引用对象)。返回指针的函数返回一个对象按值(有问题的对象是指针对象),但返回引用的函数(如GetBigClass()
)返回一个对象通过参考。它们是完全不同的语义,试图在指针和引用之间进行类比是注定要失败的。