Ile kosztuje zbyt wiele w przypadku automatycznego słowa kluczowego C ++ 11?


218

Używam nowego autosłowa kluczowego dostępnego w standardzie C ++ 11 do skomplikowanych typów szablonów, do czego, moim zdaniem, został zaprojektowany. Ale używam go również do takich rzeczy jak:

auto foo = std::make_shared<Foo>();

I bardziej sceptycznie dla:

auto foo = bla(); // where bla() return a shared_ptr<Foo>

Nie widziałem wiele dyskusji na ten temat. Wydaje się, że automożna to nadużyć, ponieważ typ jest często formą dokumentacji i kontroli poczytalności. Gdzie rysujesz linię w użyciu autoi jakie są zalecane przypadki użycia tej nowej funkcji?

Aby wyjaśnić: nie proszę o filozoficzną opinię; Proszę o zamierzone użycie tego słowa kluczowego przez standardowy komitet, ewentualnie z komentarzami na temat tego, jak zamierzone użycie jest realizowane w praktyce.

Uwaga dodatkowa: To pytanie zostało przeniesione do SE.Programmers, a następnie z powrotem do Stack Overflow. Dyskusję na ten temat można znaleźć w tym meta pytaniu .


Jest to jednak strona pytań i odpowiedzi, a nie strona dyskusji. Zadałeś bardzo ogólne pytanie i wątpię, aby ktokolwiek mógł dać ci coś innego niż wysoce subiektywne. (dlatego -1)
TravisG

15
@heishe, dodałem wyjaśnienie. Jeżeli Państwo przeczytać pytanie bardzo ogólnie, to wydaje się być pytanie subiektywne zdanie, ale naprawdę jeśli użyto autosłowa kluczowego, to wiesz, jak to miało być użyte. O to pytam, jako że ktoś, kto jest nowicjuszem w tej funkcji, jak mam jej używać?
Alan Turing

13
Widziałem tę dyskusję wszędzie, kiedy wprowadzono C # var(to znaczy, gdy ludzie wpadli na pomysł, że to wcale nie było dynamiczne pisanie). Jeśli chcesz, możesz zacząć od tego pytania i przejść do powiązanych pytań.
R. Martinho Fernandes,

2
@Lex: Albo coś jest legalne, albo nie jest; nazywanie czegoś „złym”, co jest legalne, jest z definicji subiektywne. Tzn. Nazywanie auto foo = bla();„złym” jest wyraźnie opinią, a nie faktem, co powoduje, że pytanie to jest odpowiedzią na dyskusję, co czyni go istotnym dla Programistów SE, co dokładnie wskazują na to bliskie głosy. / wzruszenie ramionami
ildjarn

3
Herb Sutter pogląd na ten temat: herbutter.com/2013/06/13/…
rafak

Odpowiedzi:


131

Myślę, że należy używać autosłowa kluczowego, ilekroć trudno jest napisać ten typ od pierwszego wejrzenia, ale typ prawej strony wyrażenia jest oczywisty. Na przykład za pomocą:

my_multi_type::nth_index<2>::type::key_type::composite_key_type::
    key_extractor_tuple::tail_type::head_type::result_type

aby uzyskać klucz złożony boost::multi_index, nawet jeśli wiesz, że tak int. Nie możesz po prostu pisać, intponieważ można to zmienić w przyszłości. autoW tym przypadku napisałbym .

Więc jeśli autosłowo kluczowe poprawia czytelność w konkretnym przypadku, użyj go. Możesz pisać, autogdy czytelnik jest oczywisty, jaki typ autoreprezentuje.

Oto kilka przykładów:

auto foo = std::make_shared<Foo>();   // obvious
auto foo = bla();                     // unclear. don't know which type `foo` has

const size_t max_size = 100;
for ( auto x = max_size; x > 0; --x ) // unclear. could lead to the errors
                                      // since max_size is unsigned

std::vector<some_class> v;
for ( auto it = v.begin(); it != v.end(); ++it )
                                      // ok, since I know that `it` has an iterator type
                                      // (don't really care which one in this context)

18
To nie wydaje się bardzo dobrą rekomendacją. Jak często nie znasz typu obiektu? (To znaczy poza szablonami.) A jeśli nie wiesz, że piszą, spójrz w górę, nie bądź leniwy i używaj auto.
Paul Manta

9
@Paul: często zdarza się, że znasz tylko najważniejszą część tego typu, np. Że jest to iterator, ale nie wiesz i nie przejmujesz się, czy jest to iterator wektorów czy iterator powiązanych lista; w takich przypadkach naprawdę nie chcesz tracić czasu i miejsca na ekranie, próbując wymyślić, jak zapisać typy.
Lie Ryan

45
Niezależnie od tego, czy osobom z C ++ to się spodoba, czy nie, C ++ 0x przyciągnie ludzi, którzy nigdy nie korzystaliby z C ++. I będą korzystać z auto w każdym miejscu.
Prof. Falken

6
@ R.MartinhoFernandes - nie, jedyne, co jest jasne, to to, że bez względu na to, cobla() dajesz foo.
Luis Machuca

8
@LuisMachuca moja odpowiedź była bezczelnym stwierdzeniem, że nieuczciwe jest podawanie w podręczniku przykładu złej nazwy zmiennej i funkcji oraz obwinianie jej braku czytelności za wnioskowanie o typie.
R. Martinho Fernandes

62

Używaj autowszędzie, gdzie możesz - szczególnie, const autoaby skutki uboczne nie były mniej niepokojące. Nie będziesz musiał martwić się typami, z wyjątkiem oczywistych przypadków, ale nadal będą dla ciebie weryfikowane statycznie i możesz uniknąć powtórzeń. Tam, gdzie autonie jest to możliwe, możesz używać wyrażeń decltypesemantycznych jako kontraktów opartych na wyrażeniach. Twój kod będzie wyglądał inaczej, ale będzie pozytywną zmianą.


12
Powiedziałbym szczególnie „const auto &”
Viktor Sehr

2
Lepsze wykorzystanie auto&&w złożonych sytuacjach edmundv.home.xs4all.nl/blog/2014/01/28/…
KindDragon

2
@KindDragon: To dobra zasada, ale wolę używać const auto&lub const autochyba że wyraźnie chcą zmutować lub przenieść.
Jon Purdy,

Używaj auto wszędzie, gdzie możesz ”. Czy to oznacza, że ​​powinienem pisać auto str = std::string();zamiast std::string str;?
Calmarius

4
Używanie auto w dowolnym miejscu sprawi, że Twój kod będzie mniej czytelny i trudniejszy do debugowania, ponieważ będziesz musiał sam wyliczyć typy podczas czytania kodu.
SubMachine,

52

Łatwo. Użyj go, jeśli nie obchodzi Cię , jaki jest typ. Na przykład

for (const auto & i : some_container) {
   ...

Chodzi mi tylko o to, ico jest w pojemniku.

To trochę jak typedefs.

typedef float Height;
typedef double Weight;
//....
Height h;
Weight w;

Tutaj nie dbam o to, czy hi wsą zmiennoprzecinkowe, czy podwajające się, tylko, że są dowolnego rodzaju odpowiedniego do wyrażania wysokości i ciężarów .

Lub zastanów się

for (auto i = some_container .begin (); ...

Tutaj zależy mi tylko na tym, aby był to odpowiedni iterator operator++(), który w pewnym sensie przypomina pisanie kaczek.

Nie można także przeliterować rodzaju lambd, więc auto f = []...jest to dobry styl. Alternatywą jest casting do, std::functionale wiąże się to z narzutem.

Nie mogę sobie wyobrazić „nadużycia” auto. Najbliższe, jakie mogę sobie wyobrazić, to pozbawienie się wyraźnej konwersji na jakiś znaczący typ - ale nie użyłbyś autodo tego, zbudowałbyś obiekt pożądanego typu.

Jeśli można usunąć niektóre redundancję w kodzie bez wprowadzania skutki uboczne, to musi być dobry, aby to zrobić.

Kontrprzykłady (zapożyczone z czyichś odpowiedzi):

auto i = SomeClass();
for (auto x = make_unsigned (y); ...)

Tutaj dbamy o to, jaki jest typ, więc powinniśmy pisać Someclass i;ifor(unsigned x = y;...


1
Um. Nie takie łatwe. Kompiluje się i biegnie, a ty właśnie postrzeliłeś się w stopę, jeśli przedmioty są nietrywialnymi obiektami - twoja iteracja wywołuje konstruktora kopii i destruktor na każdym etapie iteracji. Jeśli zamierzasz ślepo używać auto w iteratorze opartym na zakresie, prawdopodobnie powinno to być „for (const auto & item: some_container)” zamiast „for (auto item: some_container)”.
Don Hatch,

2
Nie zawsze, ale dobrze, prawdopodobnie potrzebujesz referencji. Więc co? To nie ma nic wspólnego auto.
spraff

Naprawdę nie rozumiem twojego ostatniego komentarza. Próbowałem wyjaśnić, dlaczego twoja strategia nie wygląda mi na bardzo dobrą i dlaczego ją głosuję.
Don Hatch

5
Mówię, że to, czy używasz referencji, czy nie, jest prostopadłe do tego, czy używasz auto, czy nie. Przeredaguję go, aby dodać odniesienie, ponieważ wprawdzie to zwykle jest to, co chcemy zrobić, ale jest to całkowicie nieistotne dla omawianego tematu.
spraff

43

Idź po to. Używaj autowszędzie tam, gdzie ułatwia pisanie kodu.

Każda nowa funkcja w dowolnym języku będzie nadużywana przez przynajmniej niektóre typy programistów. Tylko przez umiarkowane nadużywanie przez niektórych doświadczonych programistów (nie noobów) reszta doświadczonych programistów poznaje granice właściwego użytkowania. Ekstremalne nadużywanie jest zwykle złe, ale może być dobre, ponieważ takie nadużycia mogą prowadzić do ulepszeń funkcji lub lepszej funkcji zastępującej ją.

Ale gdybym pracował nad kodem z więcej niż kilkoma liniami jak

auto foo = bla();

gdzie typ jest wskazywany zero razy, może chciałbym zmienić te wiersze, aby zawierały typy. Pierwszy przykład jest świetny, ponieważ typ jest podawany jeden raz, i autopozwala nam uniknąć konieczności dwukrotnego pisania niechlujnych typów szablonów. Brawo dla C ++++. Ale wyraźne pokazanie typu zero razy, jeśli nie jest łatwo widoczne w pobliskiej linii, denerwuje mnie, przynajmniej w C ++ i jego bezpośrednich następcach. W przypadku innych języków zaprojektowanych do pracy na wyższym poziomie z większą abstrakcją, polimorfizmem i ogólnością, jest w porządku.


38

Na C ++ i poza 2012 r. W panelu Ask Us Anything odbyła się fantastyczna wymiana zdań między Andrei Alexandrescu, Scottem Meyerem i Herbem Sutterem na temat tego, kiedy używać, a czego nieauto . Przejdź do minuty 25:03, aby rozpocząć 4-minutową dyskusję. Wszystkie trzy głośniki dają doskonałe punkty, o których należy pamiętać, kiedy nie należy ich używać auto.

Gorąco zachęcam ludzi, aby doszli do własnych wniosków, ale moim zabraniem było używanie autowszędzie, chyba że :

  1. Utrudnia to czytelność
  2. Istnieją obawy związane z automatyczną konwersją typów (np. Z konstruktorów, przypisania, typów pośrednich szablonów, niejawnej konwersji między szerokościami całkowitymi)

Liberalne stosowanie explicitpomaga zmniejszyć obawy dotyczące tego drugiego, co pomaga zminimalizować czas, przez który ten drugi stanowi problem.

Przypominając, co powiedział Herb, „jeśli nie wykonujesz X, Y i Z, użyj auto. Dowiedz się, czym są X, Y i Z, i używaj autowszędzie indziej”.


4
Prawdopodobnie warto również linkować
Rob Starling

37

Tak, można go nadużywać ze szkodą dla czytelności. Sugeruję używanie go w kontekstach, w których dokładne typy są długie, niewymienne lub nieistotne dla czytelności, a zmienne są krótkotrwałe. Na przykład typ iteratora jest zwykle długi i nie jest ważny, więc autodziałałoby:

   for(auto i = container.begin(); i != container.end(); ++i);

auto tutaj nie szkodzi czytelności.

Innym przykładem jest typ reguły parsera, który może być długi i skomplikowany. Porównać:

   auto spaces = space & space & space;

z

r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&> spaces = 
   space & space & space;

Z drugiej strony, gdy typ jest znany i jest prosty, o wiele lepiej jest, jeśli podano wyraźnie:

int i = foo();

zamiast

auto i = foo();

2
Oczywiście posiadanie opartej na zakresie pętli dla języka sprawia, że ​​Twój pierwszy przykład jest mniej ekscytujący. 8v)
Fred Larson

@Fred: typ nadal może być nieporęczny (myślę, że pojemniki asocjacyjne)
Matthieu M.,

3
@Fred: Za każdym razem, gdy twoje granice nie są begin()i end(), lub twój rozmiar kroku jest inny niż jeden, lub gdy modyfikujesz kontener w pętli, instrukcja oparta na zakresie nie pomoże.
Dennis Zickefoose

6
@geotavros: A r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&>robi?
Dennis Zickefoose

7
@geotavros: Lub możesz zobaczyć, jaki spacejest typ , i poszukać tego. To w każdym razie bardziej użyteczna informacja ... w końcu problemem nie jest „jaki typ jest ta nowa zmienna”, ale „co to space & space & spaceznaczy?” Rzeczywistym rodzajem wyrażenia jest po prostu hałas.
Dennis Zickefoose

19

auto może być bardzo niebezpieczne w połączeniu z szablonami wyrażeń, które są często używane przez biblioteki algebry liniowej, takie jak Eigen lub OpenCV.

auto A = Matrix(...);
auto B = Matrix(...);
auto C = A * B; // C is not a matrix. It is a matrix EXPRESSION.
cout << C; // The expression is evaluated and gives the expected result.
... // <code modifying A or B>
cout << C; // The expression is evaluated AGAIN and gives a DIFFERENT result.

Błędy spowodowane tego typu błędami są dużym problemem podczas debugowania. Jednym z możliwych rozwiązań jest jawne rzutowanie wyniku na oczekiwany typ, jeśli masz ochotę używać auto dla stylu deklaracji od lewej do prawej.

auto C = Matrix(A * B); // The expression is now evaluated immediately.

1
Na początku wygląda to na dziwne zachowanie. Jeśli mnożę dwie macierze, nawet jeśli operacja jest leniwa, nie spodziewałbym się, że będzie podlegał ponownej ocenie, oczekiwałbym, że zachowa swój oceniany stan po początkowej ocenie. Jeśli chcesz zmienić parametry bez modyfikacji oryginalnych parametrów, czy i tak nie musiałbyś zrekonstruować wyrażenia? Czy może jest przeznaczony do sytuacji przetwarzania strumieniowego, w której oryginalne parametry ciągle się zmieniają, ale procedura pozostaje taka sama?
JAB

1
Niezależnie od tego, czy A*Bwyrażenie jest kopiowane do autozmiennej, czy czegoś innego, opisywane zachowanie jest nadal obecne.
xtofl

Użycie nie powoduje błędu auto.
Jim Balter

@JAB: Został zaprojektowany w celu obsługi uproszczeń i synergii między operacjami, na przykład diag(A * B)nie musi marnować cykli obliczania elementów nie przekątnych.
Ben Voigt,

Zauważyłem również kod typu „for (auto o: vecContainer)”, gdzie „o” był ciężkim obiektem, który jest kopiowany za każdym razem. Moją rekomendacją byłoby użycie tego do tego, co pierwotnie było zamierzone, to znaczy szablonów (z trudnymi wytycznymi dedukcyjnymi) i pracochłonnego typedefa. Nawet wtedy musisz uważać i odróżniać auto od auto &.
gast128

10

Używam autobez ograniczeń i nie napotkałem żadnego problemu. Czasem nawet używam go do takich prostych typów jak int. To sprawia, że ​​c ++ jest dla mnie językiem wyższego poziomu i pozwala zadeklarować zmienną w c ++ jak w Pythonie. Po napisaniu kodu python nawet czasami piszę np

auto i = MyClass();

zamiast

MyClass i;

Jest to jeden przypadek, w którym powiedziałbym, że jest to nadużycie autosłowa kluczowego.

Często nie mam nic przeciwko temu, jaki jest dokładnie typ obiektu, bardziej interesuje mnie jego funkcjonalność, a ponieważ nazwy funkcji ogólnie mówią coś o obiektach, które zwracają, autonie boli: na przykład auto s = mycollection.size()mogę zgadywać, że sto będzie rodzaj liczby całkowitej, aw rzadkich przypadkach, gdy zależy mi na dokładnym typie, sprawdźmy prototyp funkcji (to znaczy wolę sprawdzać, kiedy potrzebuję informacji, niż a priori, gdy kod jest zapisywany, po prostu na wypadek, gdyby kiedyś był przydatny, jak w int_type s = mycollection.size()).

Odnośnie tego przykładu z zaakceptowanej odpowiedzi:

for ( auto x = max_size; x > 0; --x )

W moim kodzie nadal używam autow tym przypadku, a jeśli chcę xbyć bez znaku, używam funkcji narzędziowej o nazwie say make_unsigned, która jasno wyraża moje obawy:

for ( auto x = make_unsigned(max_size); x > 0; --x )

zrzeczenie się odpowiedzialności: Po prostu opisuję swoje zastosowanie, nie jestem kompetentny do udzielania porad!


1
@ChristianRau: nie był sarkastyczny. Zauważ, że nie poleciłem użycia auto i = MyClass().
rafak

3
Follow-up: patrz: herbsutter.com/2013/06/13/... . Użycie np. as_unsignedJest tam zalecane, a nawet auto w = widget{};.
rafak

3

Jednym z głównych problemów z programem C ++ jest to, że pozwala on na użycie niezainicjowanej zmiennej . To prowadzi nas do nieprzyjemnego, deterministycznego zachowania programu. Należy zauważyć, że nowoczesny kompilator wyświetla teraz odpowiednie komunikaty / komunikaty ostrzegawcze, jeśli program się męczy.

Aby to zilustrować, rozważ poniższy program c ++:

int main() {
    int x;
    int y = 0;
    y += x;
}

Jeśli skompiluję ten program przy użyciu nowoczesnego kompilatora (GCC), wyświetli ostrzeżenie. Takie ostrzeżenie może nie być bardzo oczywiste, jeśli pracujemy z prawdziwym złożonym kodem produkcyjnym.

main.cpp: W funkcji 'int main ()':

main.cpp: 4: 8: ostrzeżenie : „x” jest używane niezainicjowane w tej funkcji [-Wuninitialized]

y + = x;

    ^

================================================== =============================== Teraz, jeśli zmienimy nasz program korzystający z auto , a następnie skompilujemy, otrzymamy:

int main() {
    auto x;
    auto y = 0;
    y += x;
}

main.cpp: W funkcji 'int main ()':

main.cpp: 2: 10: błąd : deklaracja „auto x” nie ma inicjatora

 auto x;

      ^

W przypadku auto nie jest możliwe użycie niezainicjowanej zmiennej. Jest to główna zaleta, którą możemy uzyskać (za darmo), jeśli zaczniemy korzystać z auto .

Ta koncepcja i inne super super nowoczesny C ++ koncepcja wyjaśnia ekspert C ++ Herb migawki w jego CppCon14 Dyskusja:

Powrót do podstaw! Podstawy nowoczesnego stylu C ++


2
Tak. Aby określić typ, który możesz zainicjować jako 0i, 0u, 0l, 0ul, 0.0f, 0.0, a nawet int (), unsigned (), double () itp.
Robinson

6
Ten argument jest absurdalny. Mówisz „nie możesz zapomnieć o inicjalizatorze, ponieważ pojawi się błąd kompilatora”, ale wymaga to zapamiętania użycia auto.
Wyścigi lekkości na orbicie

1
@LightnessRacesinOrbit: Zrozumiałem (nauczyłem się) tę koncepcję z przemówienia Herb Suttera. Znalazłem to logiczną / praktyczną radę z rozmowy na temat ziół, dlatego postanowiłem podzielić się nią ze społecznością.
Mantosh Kumar

2
Nie sądzę, żeby to była dobra motywacja do korzystania z auto. Wystarczy włączyć flagę ostrzegawczą kompilatora, aby użyć niezainicjowanych zmiennych i zająć się wszystkimi ostrzeżeniami. To nie znaczy, należy nie używać auto- ale nie trzeba go aboid ten problem.
einpoklum

2

Jednym z zagrożeń, które zauważyłem, są odniesienia. na przykład

MyBigObject& ref_to_big_object= big_object;
auto another_ref = ref_to_big_object; // ?

Problem w tym, że inny_ref nie jest tak naprawdę referencją, w tym przypadku jest to MyBigObject zamiast MyBigObject &. W końcu kopiujesz duży obiekt, nie zdając sobie z tego sprawy.

Jeśli otrzymujesz referencję bezpośrednio z metody, możesz nie myśleć o tym, co to właściwie jest.

auto another_ref = function_returning_ref_to_big_object();

potrzebujesz „auto &” lub „const auto &”

MyBigObject& ref_to_big_object= big_object;
auto& another_ref = ref_to_big_object;
const auto& yet_another_ref = function_returning_ref_to_big_object();

1

Użyj autotam, gdzie ma to sens, aby wywnioskować typ. Jeśli masz coś, o czym wiesz, że jest liczbą całkowitą lub wiesz, że jest to ciąg znaków, po prostu użyj int / std :: string itp. Nie martwiłbym się o „nadużywanie” funkcji języka, chyba że dojdzie do absurdu, lub zaciemnia kod.

W każdym razie taka jest moja opinia.


4
„gdzie to ma sens ...” to podchwytliwa część. Programiści mogą tak pochłonąć szczegóły kodowania, że ​​tracą poczucie sensu dla innych programistów, w szczególności dla przyszłych opiekunów.
DarenW

To prawda, chociaż myślę, że dość łatwo jest powiedzieć, kiedy jest niejednoznaczny. W razie wątpliwości użyj komentarza!
LainIwakura

1
Czy nie ma sensu używać typu?
Michaił

Niektórzy programiści twierdzą, że należy zawsze wnioskować o typie !
Arafangion,

Użyj komentarza ...... lub po prostu wpisz i nie potrzebujesz komentarza?
user997112

1

autoSłowo kluczowe może być użyte tylko dla zmiennej lokalnej, a nie do argumentów lub członków klasy / struct. Dzięki temu korzystanie z nich w dowolnym miejscu jest bezpieczne i opłacalne. Często ich używam. Typ jest wywnioskowany w czasie kompilacji, debuger pokazuje typ podczas debugowania, sizeofraportuje go poprawnie, decltypedaje prawidłowy typ - nie ma szkody. Nigdy nie liczę autojako nadużywane, nigdy!


0

TL; DR: patrz zasada praktyczna na dole.

Odpowiedź Zaakceptowany proponuje następujące równania:

Używaj, autogdy trudno jest powiedzieć, jak pisać na pierwszy rzut oka, ale rodzaj prawej strony wyrażenia jest oczywisty.

Ale powiedziałbym, że to zbyt restrykcyjne. Czasami nie dbam o typy, ponieważ stwierdzenie to jest wystarczająco pouczające, a ja nie zawracam sobie głowy, aby znaleźć czas na jego opracowanie. Co mam przez to na myśli? Rozważ przykład, który pojawił się w niektórych odpowiedziach:

auto x = f();

Co sprawia, że ​​jest to przykład niewłaściwego użycia auto? Czy to moja ignorancja co do f()typu zwrotu? Cóż, może rzeczywiście pomóc, gdybym to wiedział, ale - to nie jest moja główna troska. Problemem jest znacznie więcej xi f()są one zupełnie bez znaczenia. Gdybyśmy mieli:

auto nugget = mine_gold();

zamiast tego zwykle nie dbam o to, czy zwracany typ funkcji jest oczywisty, czy nie. Czytając to zdanie, wiem, co robię i wiem wystarczająco dużo o semantyce wartości zwracanej, aby nie czuć, że muszę także znać jej typ.

Więc moja odpowiedź brzmi: używaj, autogdy kompilator na to pozwala, chyba że:

  • Uważasz, że nazwa zmiennej wraz z wyrażeniem inicjalizacji / przypisania nie zapewnia wystarczających informacji o tym, co robi instrukcja.
  • Czujesz, że nazwa zmiennej wraz z wyrażeniem inicjalizacji / przypisania dostarcza „wprowadzających w błąd” informacji o tym, jaki powinien być typ - tj. Jeśli musiałbyś zgadnąć, co przychodzi zamiast auto, byłbyś w stanie zgadywać - i byłoby to źle, a to fałszywe założenie ma konsekwencje w dalszej części kodu.
  • Chcesz wymusić inny typ (np. Odwołanie).

I również:

  • Wolę podać sensowną nazwę (która nie zawiera oczywiście nazwy typu) przed zastąpieniem autojej konkretnym typem.

-3

Jednym z moich gorzkich doświadczeń autojest używanie go z wyrażeniami lambda :

auto i = []() { return 0; };
cout<<"i = "<<i<<endl; // output: 1 !!!

Właściwie tutaj ijest rozwiązany wskaźnik funkcji int(*)(). Jest to po prostu proste cout, ale wyobraź sobie, jaki rodzaj złych błędów kompilacji / środowiska wykonawczego może powodować, gdy jest używany z template.

Należy unikać auto takich wyrażeń i wstawić odpowiedni returntyp (lub kontrolowany decltype())

Prawidłowe użycie powyższego przykładu to:

auto i = []() { return 0; }(); // and now i contains the result of calling the lambda  

7
Wykonałeś okropną robotę, tłumacząc, co to ma wspólnego z automatem. Utworzyłeś funkcję, a następnie ją wydrukowałeś ... OK?
Dennis Zickefoose

5
@iammilind: i co to ma wspólnego z auto?
R. Martinho Fernandes,

7
Uważam, że jest bardzo mało prawdopodobne, aby ktoś chciał ()zakończyć. Lambdy mają działać jako funkcje i stąd pochodzi konwersja wskaźnika funkcji. Jeśli chcesz to nazwać od razu, po co w ogóle używać lambda? auto i = 0;działa raczej dobrze.
R. Martinho Fernandes,

4
Czy potrafisz przynajmniej opisać scenariusz, w którym auto x = []() { /* .... whatever goes in here ... */ }()jest lepszy niż auto x = /* .... whatever goes in here ... */;, tj. To samo, bez lambda? Uważam to za raczej bezcelowe, z tego samego powodu auto x = 42 + y - 42jest bezcelowe.
R. Martinho Fernandes,

6
-1 to nie jest wina auto. Typu lambda nie można przeliterować, więc wymagane jest auto , jeśli zapomnisz wywołać funkcję, to jest twój własny punkt obserwacyjny! Równie przypadkowo można umieścić niewywołany wskaźnik funkcji w printf C.
spraff
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.