C ++ 11 "авто" семантика - PullRequest
       17

C ++ 11 "авто" семантика

64 голосов
/ 17 декабря 2011

Когда я использую 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 ]

77 голосов
/ 17 декабря 2011

Правило простое: это то, как вы его объявляете.

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
13 голосов
/ 17 декабря 2011

§7.1.6.4 [dcl.spec.auto] p6

Как только тип идентификатор объявления определен в соответствии с 8.3, тип объявленной переменной с использованием объявления-идентификатор определяется по типу его инициализатора с использованием правил вывода аргументов шаблона.

Это означает только то, что 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);.)

9 голосов
/ 07 декабря 2013

Все, что вы получаете с правой стороны (от "="), никогда не является ссылкой. Точнее говоря, результат выражения никогда не является ссылкой. В этом свете обратите внимание на разницу между результатами в примере.

#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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...