Czy jest jakiś powód, aby używać słowa kluczowego „auto” w C ++ 03?


85

Zwróć uwagę, że to pytanie zostało pierwotnie opublikowane w 2009 r., Zanim C ++ 11 został ratyfikowany i zanim znaczenie autosłowa kluczowego zostało drastycznie zmienione. Udzielone odpowiedzi dotyczą tylko C ++ 03 znaczenia auto- czyli określonej klasy pamięci masowej - a nie znaczenia C ++ 11 auto- czyli automatycznego odejmowania typów. Jeśli szukasz porady, kiedy używać C ++ 11 auto, to pytanie nie dotyczy tego pytania.

Przez długi czas myślałem, że nie ma powodu, aby używać staticsłowa kluczowego w C, ponieważ zmienne zadeklarowane poza zakresem bloków były niejawnie globalne. Potem odkryłem, że zadeklarowanie zmiennej jako mieszczącej się staticw zakresie blokowym nadałoby jej stały czas trwania, a zadeklarowanie jej poza zakresem bloku (w zakresie programu) dałoby jej zakres plikowy (można uzyskać do niego dostęp tylko w tej jednostce kompilacji).

Pozostaje mi więc tylko jedno słowo kluczowe, którego (być może) jeszcze w pełni nie rozumiem: autosłowo kluczowe. Czy jest inne znaczenie niż „zmienna lokalna”? Cokolwiek robi, co nie jest robione domyślnie dla ciebie, gdziekolwiek chcesz go użyć? Jak zachowuje się autozmienna w zakresie programu? A co ze static autozmienną w zakresie pliku? Czy to słowo kluczowe ma inny cel niż tylko istnienie kompletności ?

Odpowiedzi:


74

autojest specifier klasa przechowywania, static, registeri externzbyt. W deklaracji można użyć tylko jednego z tych czterech elementów.

Zmienne lokalne (bez static) mają automatyczny czas trwania, co oznacza, że ​​żyją od początku ich definicji do końca swojego bloku. Umieszczanie przed nimi auto jest zbędne, ponieważ i tak jest to ustawienie domyślne.

Nie znam żadnego powodu, aby używać go w C ++. W starszych wersjach C, które mają niejawną regułę int, możesz użyć jej do zadeklarowania zmiennej, jak w:

int main(void) { auto i = 1; }

Aby uczynić poprawną składnię lub ujednoznacznić z wyrażenia przypisania w przypadku, gdy przypadek ijest w zakresie. Ale to i tak nie działa w C ++ (musisz określić typ). Co zabawne, standard C ++ pisze:

Obiekt zadeklarowany bez specyfikatora klasy pamięci w zakresie blokowym lub zadeklarowany jako parametr funkcji ma domyślnie automatyczny czas trwania. [Uwaga: stąd specyfikator automatyczny jest prawie zawsze nadmiarowy i rzadko używany; jednym z zastosowań auto jest jawne odróżnienie instrukcji deklaracji od instrukcji wyrażenia (6.8). - notatka końcowa]

który odnosi się do następującego scenariusza, który może być rzutem ado intlub deklaracją zmiennej atypu intmającej wokół zbędne nawiasy a. Zawsze przyjmuje się, że jest to deklaracja, więc autonie dodałbym tutaj niczego przydatnego, ale zamiast tego zrobiłby to dla człowieka. Ale z drugiej strony, człowiekowi byłoby lepiej, gdyby usunął zbędne nawiasy wokół a, powiedziałbym:

int(a);

Biorąc pod uwagę nowe znaczenie autoprzybycia z C ++ 0x, odradzałbym używanie go ze znaczeniem C ++ 03 w kodzie.


4
Kompilatory C ++ często miały niejawne int dla wartości zwracanych z funkcji, w ARM kilka dni przed standardem ... Przed EMPIRE ...
Daniel Earwicker,

1
Właśnie rozpoznałem to jako sposób, w jaki mój kompilator powiedział mi, że zapomniałem zadeklarować funkcję. Powiedziałoby mi, że moje użycie funkcji różniło się od sposobu, w jaki została zadeklarowana z powodu niejawnej int.
Carson Myers,

29
Najlepsze jest to, że programiści zwykli pisać „auto” (cztery litery), aby uchronić się przed pisaniem „int” (trzy litery).
Max Lybbert,

30
@Max - hej, wiele osób mówi „double-u-double-u-double-u” jako skrót od „World Wide Web”.
Daniel Earwicker

3
@smichak nie, „volatile” to kwalifikator typu. Zamiast określać, gdzie przechowywać wartość, zmienia zachowanie zapisu i odczytu z obiektu o zmiennym typie kwalifikowanym. Mogą istnieć nietrwałe kwalifikowane zmienne stosu (klasa automatycznego przechowywania), a także niestabilne kwalifikowane zmienne statycznego czasu trwania przechowywania (lokalna „statyczna” klasa pamięci, zmienne nielokalne). Poza tym nie wiem, czy „register volatile” jest poprawną kombinacją :)
Johannes Schaub - litb

86

W C ++ 11 automa nowe znaczenie: pozwala automatycznie wywnioskować typ zmiennej.

Dlaczego jest to kiedykolwiek przydatne? Rozważmy podstawowy przykład:

std::list<int> a;
// fill in a
for (auto it = a.begin(); it != a.end(); ++it) {
  // Do stuff here
}

autoTam tworzy iterator typu std::list<int>::iterator.

Może to znacznie ułatwić odczytanie bardzo skomplikowanego kodu.

Inny przykład:

int x, y;
auto f = [&]{ x += y; };
f();
f();

Tam autowydedukował typ wymagany do przechowywania wyrażenia lambda w zmiennej. Wikipedia dobrze opisuje ten temat.


4
Nadal nie jestem pewien, czy jest to świetne zastosowanie auto. Kod powinien być łatwy do odczytania, a nie do napisania!
DanDan

38
Nie wiem jak Ty, ale uważam to za dużo łatwiejsze do odczytania niż spam typu iteracyjnego.
Podsumowanie

17
A jeśli z jakiegoś powodu zdecydujesz się zmienić klasę z listy <int> na inną, nie musisz szukać każdej deklaracji iteratora i zmieniać jej.
roslav

2
@KarateSnowMachine: Jeśli chciałbyś mieć stałą, użyłbyś „const auto” zamiast „auto”.
darth happyface

4
@darth const auto it = a.begin();dałoby ci const iterator, a nie const_iterator. Nadal możesz zmienić element, ale ++itskompilowanie się nie powiedzie. Aby otrzymać const_iterator, należy użyćauto it = a.cbegin();
fredoverflow,

35

W tej chwili słowo kluczowe auto nie ma żadnego zastosowania. Masz rację, że po prostu odtwarza domyślną klasę pamięci zmiennej lokalnej, a naprawdę użyteczną alternatywą jest static.

Ma zupełnie nowe znaczenie w C ++ 0x. To daje wyobrażenie o tym, jak bezużyteczne było to!


1
o człowieku, czy to kiedykolwiek bezużyteczne. Podoba mi się jednak nowe znaczenie. To sprawia, że ​​kod jest znacznie mniej rozwlekły i zbędny.
Carson Myers,

Tak, użycie odpowiednika w C # prawdopodobnie spowoduje ogromną różnicę. Bardziej w C ++, jeśli używasz szablonów wyrażeń, w których typy są tak złożone, że nigdy nie miały być zapisywane ręcznie.
Daniel Earwicker,

7

GCC ma specjalne zastosowanie autodla funkcji zagnieżdżonych - zobacz tutaj .

Jeśli masz zagnieżdżoną funkcję, którą chcesz wywołać przed jej definicją, musisz ją zadeklarować za pomocą auto.


jest to świetna, choć zależna od kompilatora, implementacja auto. Dzięki za badania :)
Carson Myers

3

„auto” rzekomo mówi kompilatorowi, aby sam zdecydował, gdzie umieścić zmienną (pamięć lub rejestr). Jego analogiem jest „rejestr”, który rzekomo mówi kompilatorowi, aby próbował zachować go w rejestrze. Nowoczesne kompilatory ignorują oba, więc Ty też powinieneś.


1
Niezupełnie - jeśli zadeklarujesz to za pomocą "register", kompilatory nie pozwolą ci użyć operatora adresu (& foo) na zmiennej, ponieważ, no cóż, nie istnieje ona nigdzie w pamięci (a więc nie ma adresu).
Tim Čas

3

Używam tego słowa kluczowego, aby jawnie udokumentować, kiedy jest to krytyczne dla funkcji, aby zmienna została umieszczona na stosie, dla procesorów opartych na stosie. Ta funkcja może być wymagana podczas modyfikowania stosu przed powrotem z funkcji (lub procedury obsługi przerwania). W tym przypadku oświadczam:

auto unsigned int auiStack[1];   //variable must be on stack

Następnie mam dostęp poza zmienną:

#define OFFSET_TO_RETURN_ADDRESS 8     //depends on compiler operation and current automatics
auiStack[OFFSET_TO_RETURN_ADDRESS] = alternate_return_address;

Zatem autosłowo kluczowe pomaga udokumentować zamiar.


Zakładam, że to tylko sygnalizacja zamiaru, ponieważ słowo kluczowe w rzeczywistości nie wymusza umieszczania stosu, bardziej niż zwykłe pominięcie go.
underscore_d

2

Według Stroustrupa, w „The C Programming Language” (4. wydanie, obejmujące C 11), użycie słowa „auto” ma następujące główne przyczyny (sekcja 2.2.2) (cytowane są słowa Stroustrupa):

1)

Definicja jest w dużym zakresie, w którym chcemy, aby typ był wyraźnie widoczny dla czytelników naszego kodu.

Dzięki „auto” i jego niezbędnemu inicjalizatorowi możemy od razu poznać typ zmiennej!

2)

Chcemy jasno określić zakres lub precyzję zmiennej (np. Double zamiast float)

Moim zdaniem przypadek, który tu pasuje, to coś takiego:

   double square(double d)
    {
        return d*d; 
    }

    int square(int d)
    {
        return d*d; 
    }

    auto a1 = square(3);

    cout << a1 << endl;

    a1 = square(3.3);

    cout << a1 << endl;

3)

Używając 'auto' unikamy nadmiarowości i pisania długich nazw typów.

Wyobraź sobie długą nazwę typu z iteratora opartego na szablonach:

(kod z sekcji 6.3.6.1)

template<class T> void f1(vector<T>& arg) {
    for (typename vector<T>::iterator p = arg.begin(); p != arg.end();   p)
        *p = 7;

    for (auto p = arg.begin(); p != arg.end();   p)
        *p = 7;
}

1

W starym kompilatorze auto było w ogóle jednym ze sposobów zadeklarowania zmiennej lokalnej. Nie możesz deklarować zmiennych lokalnych w starych kompilatorach, takich jak Turbo C bez słowa kluczowego auto lub czegoś podobnego.


1

Nowe znaczenie słowa kluczowego auto w C ++ 0x zostało bardzo ładnie opisane przez Stephana T. Lavaveja z Microsoftu w ogólnodostępnym wykładzie wideo na temat STL, który można znaleźć na stronie MSDN Channel 9 tutaj .

Wykład warto obejrzeć w całości, ale część dotycząca słowa kluczowego auto znajduje się w około 29 minucie (w przybliżeniu).


0

Czy jest jakieś inne znaczenie słowa „auto” inne niż „zmienna lokalna”?

Nie w C ++ 03.

Cokolwiek robi, co nie jest robione domyślnie dla ciebie, gdziekolwiek chcesz go użyć?

Nic, w C ++ 03.

Jak zachowuje się zmienna automatyczna w zakresie programu? A co ze statyczną zmienną automatyczną w zakresie pliku?

Słowo kluczowe nie jest dozwolone poza treścią funkcji / metody.

Czy to słowo kluczowe ma inny cel [w C ++ 03] niż tylko istnienie dla kompletności?

O dziwo, tak. Kryteria projektowe C ++ obejmowały wysoki stopień wstecznej kompatybilności z C. C miało to słowo kluczowe i nie było żadnego powodu, aby go zakazać lub przedefiniować jego znaczenie w C ++. Tak więc celem była jedna niezgodność mniej z C.

Czy to słowo kluczowe ma inny cel w języku C niż tylko istnienie kompletności?

Dowiedziałem się jednego dopiero niedawno: łatwość przenoszenia starożytnych programów z B. C wyewoluowało z języka o nazwie B, którego składnia była dość podobna do składni C. Jednak B nie miał żadnych typów. Jedynym sposobem zadeklarowania zmiennej w B było określenie jej typu przechowywania ( autolub extern). Lubię to:

auto i;

Ta składnia nadal działa w języku C i jest równoważna

int i;

ponieważ w C klasa pamięci jest domyślnie ustawiona na auto, a typ domyślny to int. Wydaje mi się, że każdy program, który powstał w B i został przeniesiony do C, był wtedy dosłownie pełen autozmiennych.

C ++ 03 nie zezwala już na implicit int w stylu C, ale zachował autosłowo kluczowe, które nie jest już dokładnie przydatne, ponieważ w przeciwieństwie do niejawnego int, nie było wiadomo, że powoduje jakiekolwiek problemy w składni C.

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.