В C++11 "авто" семантика
когда я использую 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?
3 ответа:
правило простое: это то, как вы его объявляете.
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
как только тип a declarator-id была определена в соответствии с 8.3, тип объявленной переменной с помощью 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 }