C ++ 11 “автоматична” семантика


76

Коли я використовую 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?

Відповіді:


87

Правило просте: це те, як ви це заявляєте.

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

6
Зверніть увагу, що // pointerце насправді не потрібно. Крім того, те, що один компілятор видає цей результат, не означає, що він відповідає стандарту. ;) У цьому випадку це правильно, хоча можна дати кращі пояснення, що саме відбувається (виведений тип "занепав").
Xeo

@Nikos Перегляд цього питання (і відповідей) через роки… і виявляється, бувають випадки, коли тип може відрізнятися: універсальні посилання . В основному, декларації like auto&& a = ...та T&& b = ...(у шаблонах) визначатимуть lvalue або rvalue, залежно від того, до чого оцінюється вираз.
Alex B

14

§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);.)


Отже, що саме це означає для циклів for-loop на основі діапазону? Я хоч і означав, що вони є побічними посиланнями (що мені здається логічним), але просто виявив, що цього не сталося в одному випадку.
залишилося близько

3
@leftaroundabout: Це не логічно. autoТам працює точно так само. for(auto val : range)завжди буде копіювати, for(auto& ref : range)завжди буде посиланням. А заплутати ще більше for(auto&& x : range)буде T&&або T&залежно від того *begin(range), поверне значення або посилання.
Xeo

9

Все, що ви отримуєте з правого боку ("="), ніколи не є посиланням. Більш конкретно результат виразу ніколи не є посиланням. У цьому світлі зверніть увагу на різницю між результатами на прикладі.

#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
}

1
Будь ласка, додайте решту прикладу! Це найкоротша відповідь, але вам потрібно прочитати іншу, щоб зрозуміти її ...
Люк Варт

1
Це перше речення - саме те, що я шукав. Дякую.
Віктор Ейкхаут
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.