Чи є недолік у оголошенні змінних з авто в C ++?


143

Здається, що autoв C ++ 11 було додано досить значну особливість, яка, здається, відповідає багатьом новим мовам. Як і в такій мові, як Python, я не бачив явної декларації змінної (я не впевнений, чи можливо це за допомогою стандартів Python).

Чи є недолік використання autoоголошень змінних, а не явного їх оголошення?


1
Дивіться також: stackoverflow.com/questions/6434971/… , stackoverflow.com/questions/15254461/… , stackoverflow.com/questions/6900459/… , stackoverflow.com/questions/8430053/is-c11-auto-type-dangerous і, можливо, інші. Не впевнений, чи це точні дублікати, але вони безумовно кандидати.
Коді Грей

3
Єдиним недоліком, який я виявив, було, коли мені довелося перенести базу коду на платформу (консоль), компілятор якої не підтримував (і не мав наміру підтримувати) функції C ++ 11!
Сем

7
Просто для повноти GotW # 94 "Майже завжди авто": biljeutter.com/2013/08/12/…
Річард Кріттен

1
Я слухав cppcast і згадувався про автоматичне зіткнення б / в і список ініціалізаторів списку. Я спробую знайти цей подкаст.
Абхінав Гауніял

2
Перший недолік, який я думаю, впливає на читабельність коду
ggrr

Відповіді:


111

Ви запитували лише про недоліки, тому я висвітлюю деякі з них. При хорошому використанні autoмає і кілька переваг. Недоліки є наслідком простоти зловживань та збільшення потенціалу поведінки коду ненавмисно.

Основний недолік полягає в тому, що, використовуючи auto, ви не обов’язково знаєте тип створюваного об'єкта. Також бувають випадки, коли програміст може очікувати, що компілятор виведе один тип, але компілятор невпинно виводить інший.

Дано декларацію на кшталт

auto result = CallSomeFunction(x,y,z);

вам не обов’язково знати знання про тип result. Це може бути int. Це може бути вказівник. Це може бути щось інше. Усі вони підтримують різні операції. Ви також можете різко змінити код незначною зміною

auto result = CallSomeFunction(a,y,z);

оскільки залежно від того, які перевантаження існують для CallSomeFunction()типу результату, можуть бути абсолютно різними - і наступний код може, таким чином, вести себе зовсім інакше, ніж передбачалося. Ви можете раптом викликати повідомлення про помилку в більш пізньому коді (наприклад, згодом намагаєтеся знешкодити int, намагаючись змінити щось, що є зараз const). Більш зловісна зміна полягає в тому, коли ваша зміна проходить повз компілятора, але наступний код веде себе різними і невідомими - можливо, баггі - способами.

Не маючи явних знань про тип деяких змінних, тому ускладнюється жорстке обґрунтування твердження про те, що код працює за призначенням. Це означає більше зусиль для обгрунтування тверджень про «придатність до мети» у областях з високою критичністю (наприклад, критично важливими для безпеки або місією).

Іншим, більш поширеним недоліком, є спокуса програміста використовувати autoв якості тупого інструменту, щоб змусити збирати код, а не думати про те, що робить код, і працювати над тим, щоб його правильно виправити.


58
Цікаво зауважити, що якщо подібні приклади є недоліком використання auto, то більшість мов, які набирають качку, зазнають такого недоліку в дизайні!
Лебен Аса

11
Якщо CallSomeFunction()повертає інший тип залежно від послідовності його аргументів, це недолік дизайну CallSomeFunction(), а не проблема auto. Якщо ви не читаєте документацію функції, яку ви використовуєте до її використання, це дефект програміста, а не проблема auto. - Але я розумію, що ви тут граєте захисника диявола, саме у Ніра Фрідмана справа набагато краща.
DevSolar

16
@DevSolar: Чому буде T CallSomeFunction(T, int, int)дефект дизайну? Очевидно, що він "повертає інший тип залежно від послідовності його аргументів".
MSalters

9
"Основний недолік полягає в тому, що, використовуючи auto, ви не обов'язково знаєте тип створюваного об'єкта." Чи можете ви детальніше роз’яснити, чому це проблема auto, а не проблема тимчасових темпіввираження? Чому це auto result = foo();погано, а foo().bar()ні?
Ендже вже не пишається SO

24
З коментарів виходить, що "недолік" трактується як причина того, що щось є неприйнятним. Недолік мовної функції є недоліком, який розробник повинен розглянути та обґрунтувати, приймаючи чи ні, тобто здійснюючи інженерні компроміси. Я не висуваю прості зауваження щодо того, чому функцію слід використовувати чи не слід використовувати.
Пітер

76

Це не є недоліком autoпринципово точно, але в практичному плані для деяких це здається проблемою. В основному, деякі люди або: а) ставляться autoдо рятувальників для типів і вимикають їх мозок при його використанні, або b) забувають, що autoзавжди виводиться на цінні типи. Це змушує людей робити такі дії:

auto x = my_obj.method_that_returns_reference();

На жаль, ми просто глибоко скопіювали якийсь об’єкт. Часто це або помилка, або продуктивність не вдається. Тоді ви можете розмахувати і іншим способом:

const auto& stuff = *func_that_returns_unique_ptr();

Тепер ви отримуєте звисаючу довідку. Ці проблеми взагалі не викликані auto, тому я не вважаю їх законними аргументами проти цього. Але, схоже, autoробить ці питання більш поширеними (з мого особистого досвіду) з причин, які я перерахував на початку.

Я думаю, що в даний час люди будуть коригувати і розуміти розподіл праці: autoвиводить базовий тип, але ви все ще хочете подумати про референтність і стійкість. Але це займає небагато часу.


Чому для початку можна глибоко скопіювати дорогий предмет?
Лоран LA RIZZA

3
@LaurentLARIZZA: Деякі класи мають конструктори копій просто тому, що вони іноді потрібні (наприклад, екземпляри std::vector). Дорога копія - це властивість не класу, а окремих об'єктів. Так method_that_returns_referenceможе посилатися на об’єкт класу, який має конструктор копій, але цей об'єкт, як правило, є досить дорогим для копіювання (і його неможливо перемістити з).
Марк ван Левенен

@MarcvanLeeuwen: Якщо копіювати об'єкт дорого і його не можна перенести, чому він зберігатиметься в std::vector? (Тому що це може, так, або тому, що ви не керуєте класом, але це не суть). Якщо копіювати дорого, (і не володіє ресурсом, оскільки він може бути скопійований), чому б не використовувати COW на об'єкті? Місцевість даних вже вбита за розміром об'єкта.
Лоран LA RIZZA

2
@LaurentLARIZZA Не копія того, що зберігається у дорогому векторі, просто скопіювати звичайний, наприклад, вектор <double>, це виділення купи + O (N) робота. Переміщення - це червона оселедець. Перший рядок, який я показав, буде копіювати, а не переміщуватись, якщо повернене посилання не є посиланням на оцінку COW насправді ні тут, ні там. Справа в тому, що дорогі для копіювання об’єкти завжди будуть.
Нір Фрідман

4
@Yakk Це не може безпечно зробити, тому що це може зрізати. Єдине безпечне, що він може зробити - = deleteце перевантаження. Хоча загалом те, що ви говорите, - це рішення. Це тема, яку я досліджував, якщо вас цікавить: nirfriedman.com/2016/01/18/… .
Нір Фрідман

51

Інші відповіді згадують недоліки на кшталт "ти насправді не знаєш, що таке тип змінної". Я б сказав, що це багато в чому пов'язане з неохайною умовою іменування в коді. Якщо ваші інтерфейси чітко названі, вам не потрібно дбати про те, який саме тип. Зрозуміло, auto result = callSomeFunction(a, b);це вам мало говорить. Але auto valid = isValid(xmlFile, schema);вам достатньо використовувати, validне піклуючись про те, який саме його тип. Зрештою, просто if (callSomeFunction(a, b)), ви також не знали б типу. Те саме з будь-якими іншими тимчасовими об'єктами на вираз. Тому я не вважаю це справжнім недоліком auto.

Я б сказав, що його основний недолік полягає в тому, що іноді точний тип повернення - це не те, з чим ти хочеш працювати. Насправді іноді фактичний тип повернення відрізняється від "логічного" типу повернення як деталі реалізації / оптимізації. Шаблони виразів є яскравим прикладом. Скажімо, у нас це є:

SomeType operator* (const Matrix &lhs, const Vector &rhs);

За логікою, ми б очікували, що SomeTypeце буде Vector, і ми, безумовно, хочемо ставитися до цього як до нашого коду. Однак можливо, що для оптимізації бібліотека алгебр, яку ми використовуємо, реалізує шаблони виразів, а фактичний тип повернення такий:

MultExpression<Matrix, Vector> operator* (const Matrix &lhs, const Vector &rhs);

Тепер проблема полягає в тому, що, MultExpression<Matrix, Vector>швидше за все, зберігатимуться внутрішньо const Matrix&і const Vector&внутрішньо; він очікує, що він перетвориться на a Vectorдо кінця свого повноцінного вираження. Якщо у нас є цей код, все добре:

extern Matrix a, b, c;
extern Vector v;

void compute()
{
  Vector res = a * (b * (c * v));
  // do something with res
}

Однак, якби ми autoтут використали , ми могли б потрапити в біду:

void compute()
{
  auto res = a * (b * (c * v));
  // Oops! Now `res` is referring to temporaries (such as (c * v)) which no longer exist
}

3
@NirFriedman Ви маєте рацію, це сильно, але я насправді відчуваю, що autoмає дуже мало недоліків, тому я стою на цьому. Інші приклади проксі-серверів тощо включають різні "конструктори струн" та подібні об'єкти, знайдені в DSL.
Ендже вже не пишається SO

2
Мене вкусили шаблони виразів і autoраніше, зокрема з бібліотеки Eigen. Це особливо складно, оскільки проблема часто не відображається в налагодженнях.
Dan

1
Використання autoтакож може перекусити при використанні матриці бібліотеки Armadillo , що робить сильне використання метапрограмування шаблонів для цілей оптимізації. На щастя, розробники додали функцію .eval (), яку можна використовувати, щоб уникнути проблем зauto
mtall

2
"Якщо ваші інтерфейси чітко названі, вам не потрібно дбати про те, який саме тип" Ваш компілятор не може перевірити правильність вашого коду, вивчаючи імена змінних. Це вся точка системи типу. Сліпо в обхід це нерозумно!
Гонки легкості на орбіті

1
@Angew: Це не є проблемою для тимчасових виробників, тому що ти зазвичай їх відразу використовуєш, що, autoяк правило, не передбачає певної перевірки типу (а плескання autoскрізь знімає безпеку цього типу так само, як і скрізь). Це не гарне порівняння.
Гонки легкості на орбіті

13

Одним з недоліків є те, що іноді ви не можете оголосити const_iteratorз auto. Ви отримаєте звичайний (не const) ітератор у цьому прикладі коду, взятого з цього питання :

map<string,int> usa;
//...init usa
auto city_it = usa.find("New York");

3
Ну, ви отримаєте підписку iteratorв будь-якому випадку, оскільки ваша карта не є const. якщо ви хочете перетворити його в a const_iterator, або вкажіть тип змінної явно як зазвичай, або витягніть метод, щоб ваша карта була const у вашому контексті find. (Я вважаю за краще останнє. SRP.)
Лоран LA RIZZA

auto city_it = static_cast<const auto&>(map).find("New York")? або, з C ++ 17, auto city_if = std::as_const(map).find("New York").
Dev Null

11

Це робить ваш код трохи важчим або стомлюючим для читання. Уявіть щось подібне:

auto output = doSomethingWithData(variables);

Тепер, щоб з'ясувати тип виводу, вам доведеться відстежити підпис doSomethingWithDataфункції.


40
Не завжди. auto it = vec.begin();набагато простіше читати, ніж std::vector<std::wstring>::iterator it = vec.begin();наприклад.
Джонатан Поттер

4
Домовились. Це залежить від випадку використання. Я міг би бути більш точним щодо цього.
Скам

1
@SeeDart Так, люди, які користуються подібними авто, роблять це неправильно.
lciamp

6
"Відслідкуйте підпис функції", якщо це не наведення миші або натискання клавіші ("слідкуйте за символом" / "перейти до декларації" / як би воно не називалося), вам потрібно або налаштувати редактор більше, або переключитися на IDE, який може це зробити без конфігурації ... Однак ваша точка все ще діє.
Гайда

6
Я помітив, що не в IDE, а в невеликих віконах різниць під час огляду чеків! З авто їх важче читати з цієї причини.
JDługosz

10

Як і цей розробник, я ненавиджу auto. Вірніше, я ненавиджу , як люди зловживають auto.

Я вважаю, що я autoдопомагаю вам написати загальний код, а не для скорочення набору тексту .
C ++ - це мова, мета якої - дозволити писати надійний код, а не мінімізувати час розробки.
Це досить очевидно з багатьох функцій C ++, але, на жаль, кілька нових, таких як, autoщо зменшують набір тексту, що вводить людей в оману, думаючи, що вони повинні почати лінуватися.

У попередні autoдні люди використовували typedefs, що було чудово, тому що typedef дозволив дизайнеру бібліотеки допомогти вам зрозуміти, яким повинен бути тип повернення, щоб їхня бібліотека працювала так, як очікувалося. Під час використання autoви знімаєте цей контроль у дизайнера класу і замість цього просите компілятора розібратися, яким він повинен бути тип, який видаляє один із найпотужніших інструментів C ++ з панелі інструментів і ризикує порушити їх код.

Як правило, якщо ви використовуєте auto, це має бути тому, що ваш код працює для будь-якого розумного типу , а не тому, що ви просто лінь записати тип, з яким він повинен працювати. Якщо ви використовуєте autoяк інструмент для допомоги ліні, то, що трапляється, ви, зрештою, починаєте вводити в свою програму непомітні помилки , як правило, спричинені неявними перетвореннями, які не відбулися через те, що ви використовували auto.

На жаль, ці помилки важко проілюструвати в короткому прикладі тут , тому що їх стислість робить їх менш переконливими , ніж фактичні приклади , які приходять в призначеному для користувача проект - тим НЕ менш, вони відбуваються легко в шаблонах важкого коду , який очікують деякі неявні перетворень прийняти місце.

Якщо ви хочете приклад, є один тут . Невелика примітка, однак: перед тим, як спробувати стрибнути і критикувати код: пам’ятайте, що багато відомих і зрілих бібліотек було розроблено навколо таких неявних перетворень, і вони є там, оскільки вони вирішують проблеми, які можуть бути важкими, якщо не неможливими вирішити інакше. Спробуйте знайти краще рішення, перш ніж критикувати їх.


3
which was great because typedef allowed the designer of the library to help you figure out what the return type should be, so that their library works as expected. When you use auto, you take away that control from the class's designer and instead ask the compiler to figure out what the type should beНе дуже вагома причина ІМО. Оновлені IDE, наприклад, Visual Studio 2015, наприклад, дозволяють перевірити тип змінної, клацнувши курсор миші auto. Це * точно * те саме, що і typedefодне.
Курка Сомбреро

@JameyD: Ви пропускаєте кілька важливих моментів: (1) Ваш аргумент IDE працює лише у тому випадку, якщо тип конкретний, а не шаблонований. IDE, можливо, не може вказати вам правильний тип у випадку залежних типів, наприклад typename std::iterator_traits<It>::value_type. (2) Вся суть полягала в тому, що виведений тип не повинен бути «точно таким же», як правильний тип, призначений попереднім конструктором коду; використовуючи auto, ви забираєте у дизайнера можливість вказати правильний тип.
користувач541686

Ви в основному говорите про проксі, про які в одній з відповідей уже згадується. Шаблони виразів та векторні <bool> дурниці - це не повсякденний код для більшості людей. У більшості ситуацій не потрібно неявних конверсій, і авто допомагає у цьому. Герб Саттер широко розповідає про переваги авто в одному зі своїх публікацій в блозі, і справа не в основному про натискання клавіш, а це стосується не лише загального коду. Крім того, перше надіслане вами посилання - повідомлення в блозі - це просто жахлива порада (саме тому він голосно критикує в своєму розділі коментарів).
Нір Фрідман

@NirFriedman: "... vector<bool>дурниця" ... пробачте? Як ви думаєте, як bitsetце реалізовано? Або ти вважаєш бітові контейнери взагалі нісенітницею ?!
користувач541686

1
@NirFriedman: Ніщо про вектор <bool> не для мене новина. Те, що я намагаюся сказати вам, і що ви відверто відмовляєтесь зрозуміти, це те, що для цього питання бітсет не відрізняється від векторного <bool> - обидва вони використовують проксі, тому що проксі вважали корисними і те, що проксі-сервера є корисними, - це реальність, яку потрібно прийняти, а не жити у відмові. Чи можете ви перестати перетворювати це на дискусію щодо того, чи вважаєте ви, що довірені особи корисні? Це не є предметом дискусій, а також, ваша думка щодо них - це лише ваша думка, а не якийсь факт.
користувач541686

6

autoне має недоліки самі по собі , і я виступаю в (ручному wavily) використовувати його всюди в новому коді. Це дозволяє вашому коду послідовно перевіряти набір тексту та постійно уникати беззвучного нарізання. (Якщо Bпоходить від Aі функція, що повертається Aраптово, повертається B, то autoповодиться так, як очікувалося, зберігає свою повернуту вартість)

Хоча застарілий код pre-C ++ 11 може покладатися на неявні перетворення, викликані використанням явно введених змінних. Зміна явно введеної змінної autoможе змінити поведінку коду , тож вам слід бути обережнішими.


Відхилення рахунків справедливо, але ви можете, будь ласка, прокоментувати чому?
Лоран LA RIZZA

Я вас не порушив, але autoє недоліки самі по собі (або принаймні - багато хто вважає, що це є). Розглянемо приклад, поданий у другому запитанні на цій панельній дискусії з Саттером, Олександреску та Майєрсом: Якщо у вас є auto x = foo(); if (x) { bar(); } else { baz(); }і foo()повертається bool- що станеться, якщо foo()зміни повернуть перерахунок (три варіанти замість двох)? autoКод буде продовжувати працювати, але привести до несподіваних результатів.
einpoklum

@einpoklum: А чи використовує boolзамість того, щоб autoщось змінити у випадку незрозумілого перерахунку? Я можу помилятися (не можу перевірити тут), але я думаю, що єдиною різницею є те, що перетворення boolвідбувається в оголошенні змінної, а не при оцінці умови в if. Якщо обсяг enumвстановлений, то перетворення в нього boolне відбудеться без явного повідомлення.
Лоран LA RIZZA

4

Ключове autoслово просто виводить тип із поверненого значення. Тому він не еквівалентний об'єкту Python, наприклад

# Python
a
a = 10       # OK
a = "10"     # OK
a = ClassA() # OK

// C++
auto a;      // Unable to deduce variable a
auto a = 10; // OK
a = "10";    // Value of const char* can't be assigned to int
a = ClassA{} // Value of ClassA can't be assigned to int
a = 10.0;    // OK, implicit casting warning

Оскільки autoвиводиться під час компіляції, він не матиме недоліків під час виконання.


1
так, він в основному робить те, що робить type()у python. Він виводить тип, він не створює нову змінну цього типу.
lciamp

2
@lciamp Насправді це було б decltype. autoспеціально для призначення змінних.
Кубік

4

Те, про що тут ніхто не згадував, але для себе варто відповісти, якщо ви запитали мене.

Оскільки (навіть якщо всі повинні знати про це C != C++) код, написаний на C, може бути легко сконструйований таким чином, щоб забезпечити базу для коду C ++ і, отже, бути спроектований без особливих зусиль для сумісності з C ++, це може бути вимогою до проектування.

Я знаю про деякі правила, де деякі чітко визначені конструкції з Cнедійсних C++і навпаки. Але це просто призведе до зламаних виконуваних файлів, і застосовується відома UB-стаття, яка в більшості випадків помічається дивними петлями, що призводять до збоїв або чого завгодно (або навіть можуть залишатися непоміченими, але це не має значення тут).

Але autoвперше 1 це змінюється!

Уявіть, що ви раніше використовували autoяк специфікатор класу зберігання та передавали код. Це навіть не обов'язково (залежно від способу його використання) "зламати"; це фактично могло мовчки змінити поведінку програми.

Це те, про що слід пам’ятати.


1 Принаймні, я вперше про це знаю.


1
Ви все одно отримаєте помилку компілятора при спробі компіляції.
Курка Сомбреро

@JameyD: Що б це зробити? Чому 2 дійсні кодові ситуації з різним значенням resutl коли-небудь помиляються?
dhein

8
Якщо ви покладаєтесь на "жоден тип не передбачає int" в C, ви заслуговуєте на всі погані речі, які ви отримаєте від цього. І якщо ви не покладаєтесь на нього, використання autoв якості специфікатора класу зберігання поряд із типом дасть вам хорошу помилку компіляції в C ++ (що в цьому випадку є хорошою справою).
Ендже вже не пишається SO

1
@Angew добре, це справа, яку я заздалегідь розглядаю, так. Я цього не роблю. Але це щось, про що слід хоча б пам’ятати.
dhein

3

Однією з причин, про яку я можу подумати, є те, що ви втрачаєте можливість примусити клас, який повертається. Якщо ваша функція або метод повернув довгі 64 біти, а ви хотіли лише 32 непідписані int, ви втрачаєте можливість контролювати це.


1
Існує static_cast, і IIRC, наприклад, Meyers 'Effective Modern C ++ навіть рекомендує використовувати його для визначення типу для автоматично введеної змінної.
Гайда

2

Як я описав у цій відповіді, auto іноді це може призвести до неприємних ситуацій, яких ви не мали наміру. Ви повинні експліцитно сказати, auto&щоб мати тип посилання, при цьому просто autoможете створити тип вказівника. Це може призвести до плутанини, опустивши специфікатор всі разом, в результаті чого копія посилання замість фактичної посилання.


2
Це не фанк. Ось що і autoробить, ніколи не виводячи посилання і constтипу. Для autoдовідки вам краще скористатися auto&&. (універсальна довідка) Якщо тип копіювати недешево або є власником ресурсу, то тип не повинен бути копіюваним для початку.
Лоран LA RIZZA

1

Ще один дратівливий приклад:

for (auto i = 0; i < s.size(); ++i)

створює попередження ( comparison between signed and unsigned integer expressions [-Wsign-compare]), оскільки iце підписаний int. Щоб цього уникнути, потрібно написати напр

for (auto i = 0U; i < s.size(); ++i)

а може й краще:

for (auto i = 0ULL; i < s.size(); ++i)

1
Так, і мене це дратує. Але дірка в мові десь інша. Щоб цей код був по-справжньому переносним, якщо припускати sizeповернення size_t, вам доведеться мати таке size_tбуквальне слово 0z. Але ви можете оголосити UDL для цього. ( size_t operator""_z(...))
Лоран LA RIZZA

1
Суто теоретичні заперечення: unsignedцілком ймовірно, вона не буде достатньо великою, щоб вмістити всі значення std::size_tархітектурних архітектур, тому в навряд чи хтось мав контейнер з абсурдно гігантською кількістю елементів, використання unsignedможе спричинити нескінченний цикл на нижньому діапазоні індексів. Хоча це навряд чи буде проблемою, його std::size_tслід використовувати для отримання чистого коду, який належним чином сигналізує про наміри. Я не впевнений, що навіть unsigned long longцього строго гарантовано достатньо, хоча на практиці це, мабуть, має бути однаковим.
підкреслити_6

@underscore_d: так, справедлива точка - unsigned long longгарантовано принаймні 64 біт, але теоретично, size_tмабуть, може бути більше, ніж це. Звичайно, якщо у вашому контейнері є> 2 ^ 64 елементи, то у вас можуть виникнути більші проблеми, щоб хвилюватися про ... ;-)
Paul R

1

Я думаю, що autoце добре, коли використовується в локалізованому контексті, де читач легко і очевидно може вивести його тип, або добре задокументований з коментарем свого типу або іменем, що визначає фактичний тип. Ті, хто не розуміє, як це працює, можуть сприймати його невірними способами, наприклад, використовувати його замість цього templateчи подібного. Ось кілька хороших та поганих випадків використання, на мою думку.

void test (const int & a)
{
    // b is not const
    // b is not a reference

    auto b = a;

    // b type is decided by the compiler based on value of a
    // a is int
}

Гарне використання

Ітератори

std::vector<boost::tuple<ClassWithLongName1,std::vector<ClassWithLongName2>,int> v();

..

std::vector<boost::tuple<ClassWithLongName1,std::vector<ClassWithLongName2>,int>::iterator it = v.begin();

// VS

auto vi = v.begin();

Функції Покажчики

int test (ClassWithLongName1 a, ClassWithLongName2 b, int c)
{
    ..
}

..

int (*fp)(ClassWithLongName1, ClassWithLongName2, int) = test;

// VS

auto *f = test;

Погане використання

Потік даних

auto input = "";

..

auto output = test(input);

Функція Підпис

auto test (auto a, auto b, auto c)
{
    ..
}

Тривіальні випадки

for(auto i = 0; i < 100; i++)
{
    ..
}

Коли ви хочете int, ви повинні ввести ще один char, якщо ви хочете auto. Це неприпустимо
Реріто

@Rerito так, це intяк легко помітити тут, а введення intкоротше. Ось чому це тривіальний випадок.
Khaled.K

0

Я здивований, що ніхто про це не згадував, але припустимо, ви що-небудь обчислюєте:

#include <iostream>
using namespace std;

int main() {
    auto n = 40;
    auto factorial = 1;

    for(int i = 1; i <=n; ++i)
    {
        factorial *= i;
    }

    cout << "Factorial of " << n << " = " << factorial <<endl;   
    cout << "Size of factorial: " << sizeof(factorial) << endl; 
    return 0;
}

Цей код виведе це:

Factorial of 40 = 0
Size of factorial: 4

Це, безумовно, не був очікуваним результатом. Це сталося тому, що було autoвиведено тип змінної факториалу, intтому що він був призначений 1.

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