C + + 11“ auto”语义

当我使用 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?
40898 次浏览

规则很简单,就是你怎么声明它。

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确定了 声明程序 ID的类型,使用 声明程序 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
}