当我使用C ++ 11 auto
时,关于将其解析为值还是引用的类型演绎规则是什么?
例如,有时很清楚:
auto i = v.begin(); // Copy, begin() returns an iterator by value
这些不太清楚:
const std::shared_ptr<Foo>& get_foo();
auto p = get_foo(); // Copy or reference?
static std::shared_ptr<Foo> s_foo;
auto sp = s_foo; // Copy or reference?
std::vector<std::shared_ptr<Foo>> c;
for (auto foo: c) { // Copy for every loop iteration?
规则很简单:它是您声明的方式。
int i = 5;
auto a1 = i; // value
auto & a2 = i; // reference
下一个例子证明了这一点:
#include <typeinfo>
#include <iostream>
template< typename T >
struct A
{
static void foo(){ std::cout<< "value" << std::endl; }
};
template< typename T >
struct A< T&>
{
static void foo(){ std::cout<< "reference" << std::endl; }
};
float& bar()
{
static float t=5.5;
return t;
}
int main()
{
int i = 5;
int &r = i;
auto a1 = i;
auto a2 = r;
auto a3 = bar();
A<decltype(i)>::foo(); // value
A<decltype(r)>::foo(); // reference
A<decltype(a1)>::foo(); // value
A<decltype(a2)>::foo(); // value
A<decltype(bar())>::foo(); // reference
A<decltype(a3)>::foo(); // value
}
输出:
value
reference
value
value
reference
value
§7.1.6.4 [dcl.spec.auto] p6
一旦已经根据8.3确定了declarator-id的类型,则使用declarator-id声明的变量的类型是使用模板参数规则从其初始化程序的类型确定的推导。
这意味着auto
不会在函数调用期间为模板参数推导建模。
template<class T>
void f(T){} // #1, will also be by-value
template<class T>
void g(T&){} // #2, will always be by-reference
请注意,无论您传递引用还是其他任何东西,#1都将始终复制传递的参数。 (除非您专门指定模板参数,例如f<int&>(intref);
。]
无论您从右侧(等于“ =”)获得什么,都绝不会成为参考。更具体地说,表达式的结果永远不会是引用。因此,请注意示例中结果之间的差异。
#include <typeinfo>
#include <iostream>
template< typename T >
struct A
{
static void foo(){ std::cout<< "value" << std::endl; }
};
template< typename T >
struct A< T&>
{
static void foo(){ std::cout<< "reference" << std::endl; }
};
float& bar()
{
static float t=5.5;
return t;
}
int main()
{
auto a3 = bar();
A<decltype(bar())>::foo(); // reference
A<decltype(a3)>::foo(); // value
}