Подтвердить что ты не робот

С++ 11 auto: что, если он получает постоянную ссылку?

Пожалуйста, взгляните на следующий простой код:

class Foo
{
public:
  Foo(){}
  ~Foo(){}

  Foo(const Foo&){}
  Foo& operator=(const Foo&) { return *this; }
};

static Foo g_temp;
const Foo& GetFoo() { return g_temp; }

Я попытался использовать auto следующим образом:

auto my_foo = GetFoo();

Я ожидал, что my_foo будет постоянной ссылкой на Foo, которая является возвращаемым типом функции. Однако тип auto Foo, а не ссылка. Кроме того, my_foo создается путем копирования g_temp. Это поведение не так очевидно для меня.

Чтобы получить ссылку на Foo, мне нужно было написать вот так:

const auto& my_foo2 = GetFoo();
      auto& my_foo3 = GetFoo();

Вопрос: Почему auto выводит возвращаемый тип GetFoo как объект, а не ссылку?

4b9b3361

Ответ 1

Прочтите эту статью: Появление и исчезновение констант в С++


Вывод типа для автоматических переменных в С++ 0x по существу такой же, как для параметров шаблона. (Насколько я знаю, единственная разница между ними состоит в том, что тип автоматических переменных можно вывести из списки инициализаторов, в то время как типы параметров шаблона могут отсутствовать.) Поэтому каждая из следующих деклараций объявляет переменные типа int (никогда const int):

auto a1 = i;
auto a2 = ci;
auto a3 = *pci;
auto a4 = pcs->i;

При выводе типа для параметров шаблона и автоматических переменных только высшие consts удаляются. Учитывая, что шаблон функции принимает указатель или ссылочный параметр, постоянство того, что указано или ссылка на него сохраняется:

template<typename T>
void f(T& p);

int i;
const int ci = 0;
const int *pci = &i;

f(i);               // as before, calls f<int>, i.e., T is int
f(ci);              // now calls f<const int>, i.e., T is const int
f(*pci);            // also calls f<const int>, i.e., T is const int

Это поведение - это старые новости, применяемые как к С++ 98, так и к С++ 03. Соответствующее поведение для автоматических переменных, конечно, новый для С++ 0x:

auto& a1 = i;       // a1 is of type int&
auto& a2 = ci;      // a2 is of type const int&
auto& a3 = *pci;    // a3 is also of type const int&
auto& a4 = pcs->i;  // a4 is of type const int&, too

Поскольку вы можете сохранить cv-квалификатор, если тип является ссылкой или указателем, вы можете сделать:

auto& my_foo2 = GetFoo();

Вместо того, чтобы указывать его как const (то же самое для volatile).

Изменить:. Почему auto выводит возвращаемый тип GetFoo() в качестве значения вместо ссылки (что было вашим основным вопросом, извините), рассмотрите это:

const Foo my_foo = GetFoo();

Вышеописанная версия создаст копию, так как my_foo - значение. Если auto должен был возвращать ссылку на lvalue, это было бы невозможно.