C ++ 11“自动”语义
当我使用C ++ 11 auto
,关于是否将parsing为值或引用,types推导的规则是什么?
例如,有时很明显:
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
下一个例子certificate了这一点:
#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的types,那么使用声明符id的声明variables的types是根据其初始化符的types使用模板参数推导的规则确定的。
这意味着在函数调用期间除了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);
)
无论你从右边(“=”)得到什么都不是一个参考。 更具体地说,expression的结果从来不是一个参考。 有鉴于此,请注意示例中的结果之间的差异。
#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 }