Czy w C / C ++ powinienem używać „const” w parametrach i zmiennych lokalnych, jeśli to możliwe?

14

To pytanie jest inspirowane pytaniem o finaljava .

Czy w C / C ++ powinienem używać, constgdy tylko jest to możliwe?

Wiem, że istnieje już podobne pytanie dotyczące używania constparametrów . Niestety to pytanie i jego odpowiedzi nie odpowiadają w pełni na moje pytanie, ponieważ dotyczą tylko parametrów funkcji, ale chciałbym również wiedzieć o innych przypadkach (np. Zmiennych lokalnych).

Ponadto prawie wszystkie odpowiedzi na to pytanie mówią, że powinniśmy skorzystać, constponieważ zawiera przydatne informacje na temat dostępności zmiennych. Wydaje się to jednak kolidować z odpowiedzią na temat używania wersji ostatecznej w Javie, która finalmoże być zbędna, jeśli nie zawiera dodatkowych informacji, dlatego należy ją pominąć, aby kod był krótki i czysty.

Czy powinienem używać, constgdy tylko jest to możliwe? Jeśli tak, to dlaczego porady dla constC ++ różnią się od porad dla finalJava?

ocomfd
źródło

Odpowiedzi:

19

Przede wszystkim, skoro wspomniałeś o Javie final, jest to zupełnie inna bestia niż const. Ostateczny oznacza, że ​​odniesienie nie może się zmienić, ale nie mówi nic o zmienności. Const idzie dalej, mówiąc „stałe odwołanie nie może mutować”, co jest znacznie silniejszą gwarancją. Aby to zrobić w Javie, stan wewnętrzny musi być ostateczny i określony w czasie budowy. Const jest o wiele łatwiejszy w użyciu, a istniejący obiekt można „awansować” na stałe const.

Tak, powinieneś używać const zawsze, gdy jest to możliwe. To sprawia, że ​​Twój kod niczego nie zmieni. Pamiętaj, że zmienna inna niż const może być przekazana do funkcji, która akceptuje parametr const. Zawsze możesz dodać const, ale nie możesz go zabrać (nie bez const cast, co jest naprawdę złym pomysłem).

Ciągła poprawność może być czasami nużąca, ale pomaga zagwarantować niezmienność. Jest to kluczowe w wielowątkowym kodzie, w którym wątki współużytkują obiekty. Usprawnia niektóre zadania: zamiast kopiować stan, wystarczy ponownie użyć tego samego niezmiennego obiektu. Biblioteki mogą akceptować parametry const, aby zapewnić programiście gwarancję, że nie, twój obiekt nie zmieni się w nieprzewidywalny sposób w czarnej dziurze, która jest wnętrznościami biblioteki.


źródło
1
Głosuj, ponieważ to wyjaśnisz finali constnie masz takich samych gwarancji.
Bill Door
2
Ciągłość polega na pisalności, a nie na zmienności.
Basilevs,
@Basilevs co się stanie, jeśli napiszesz do obiektu? Mutuje. Jak mutujesz obiekt? Napisz do tego.
4
Co się stanie, jeśli napiszesz do stałej referencji? Błąd czasu kompilacji. Co się stanie, jeśli napiszesz do obiektu, do którego odwołuje się const przez referencję inną niż const referen? Mutuje. Niezmienny obiekt nie może mutować, stąd stałe odnawianie niekoniecznie odnosi się do niezmiennego obiektu.
Basilevs,
@Basilevs twoja obserwacja dotyczy tylko stałych odniesień. Jeśli sam obiekt jest zadeklarowany jako const (nie tylko odniesienie), to jest on mniej lub bardziej niezmienny (chyba że ktoś nikczemnie odrzuca tę stałość).
Matthew James Briggs
5

Osobiście constzajmuje mi bardzo mało czasu na pisanie i bardzo mało czasu na czytanie, zwykle o wiele mniej niż zajmuje sprawdzenie, czy jakiś kod mutuje zmienną, i w rzeczywistości uniemożliwia mi pisanie błędów (czy ktoś kiedykolwiek przypadkowo zwiększył swój iterator końcowy? Itp)

Uważam również, że ścisłe stosowanie const prowadzi mnie do lepszego kodu na inne sposoby, na przykład do tworzenia funkcji pomocniczych do wykonywania nietrywialnych inicjalizacji.

Bwmat
źródło
4

Nie zgadzam się z innymi plakatami i zalecam, abyś nie używał najwyższego poziomu constdla lokalnych zmiennych i parametrów. (Odwołania i wskaźniki do const, tj. const T&Są różne, i powinieneś ich używać dla poprawności przez cały czas, gdy jest to właściwe).

Zalety najwyższego poziomu constto:

  • Wyjaśnia, że ​​zmienne lokalne nie są przeznaczone do mutacji.
  • Daje błąd kompilatora, jeśli przypadkowo spróbujesz je mutować.

Wady to:

  • Wizualny bałagan.
  • Nie można go stosować w przypadku zmiennych „pseudo-stałych”, tj. Zmiennych, które są inicjowane w jakiś sposób bardziej skomplikowane niż bezpośrednia konstrukcja, ale nie są modyfikowane po np. Użyciu getline:

    std::string line; // cannot be const
    std::getline(std::cin, line);
    // line should be const from here on out
  • Zapobiega optymalizacji wyprowadzania przy wywołaniu funkcji i powrocie:

    std::string f1();
    std::string f2(std::string s);
    std::string f3() {
      const std::string s = f1(); // s is not meant to be modified
      // but I still want the move optimization here:
      const std::string result = f2(std::move(s)); // this doesn't move
      // and I want the compiler to move out here:
      return result; // this will probably RVO, but if not, the move
                     // constructor will not be used due to the const
    }

Pracowałem nad bazą kodu, w której constczęsto używany był język lokalny , i okazało się, że w ogóle nie był pomocny, ale wypełnił kod subtelnymi pesymizacjami, jak powyżej. Ja osobiście wolę przyjąć ogólną politykę modyfikowania zmiennych tak rzadko, jak to możliwe, i uczynić funkcje wystarczająco małymi, aby użycie zmiennej było oczywiste, a nawet jeśli zostanie zmodyfikowana, złożoność funkcji jest wystarczająco niska, aby uczynić ją zmienną -kwestia.

Sebastian Redl
źródło
2
Chodzi o to, żeby przenieść się z tego miejsca, pokazując, gdzie nie używasz lokalnego w stały sposób, ponieważ (zamierzasz) zmodyfikować go za pomocą ruchu
Caleth,
1
@ Caleth Nie, o to chodzi. Nie zamierzam go modyfikować. Chcę tylko przekazać wartość lub zwrócić ją i chcę, aby była wydajna. Pod względem koncepcyjnym modyfikacja jest jedynie optymalizacją, która nie ma być obserwowalna (ponieważ zmienne nie są później używane). Praktycznie tak, jest modyfikacja, ponieważ C ++ nie ma prawdziwych destrukcyjnych ruchów (tak jak Rust). Właśnie dlatego nie chcę constna lokalnych: ponieważ zapobiega modyfikacjom technicznym, a nie tylko koncepcyjnym.
Sebastian Redl,
2
Nie chcesz modyfikować wartości , ale chcesz modyfikować zmienną . Zamiast tego możesz użyć const & zamiast i nie modyfikować żadnego
Caleth
2

Słowa constkluczowego należy używać w przypadku zmiennych lokalnych, podobnie jak parametrów. Jest to przydatne, ponieważ:

  • Łatwiej odczytać kod. Kiedy ktoś czyta deklarację zmiennej, wie, że się nie zmieni. O jedną rzecz mniej do zmartwienia podczas czytania kodu.
  • Zapobiegnij przypadkowej modyfikacji zmiennej
  • Brak kary czasu wykonywania, wszystko jest sprawdzane statycznie. To jak darmowy lunch, napisanie constpowinno zająć tylko sekundę, więc nie jest to wielka sprawa.
  • Zawsze dobrym pomysłem jest tworzenie zmiennych / parametrów w aplikacjach wielowątkowych. Nawet twoja aplikacja nie jest wielowątkowa, to wciąż dobry nawyk.
  • Dajesz kompilatorowi C ++ możliwość optymalizacji kodu.

Zauważ, że nie ma tutaj poprawnej / złej odpowiedzi. W twoim linku użytkownik, który miał najwięcej argumentów, finalnie powinien być używany lokalnie. Jednak kolejny odpowiadający zdecydowanie go polecił.

Jeśli twoja funkcja to prosta i trywialna , nie powinieneś dodawać, constponieważ wszyscy rozumieją twój zamiar. Jeśli jednak logika w Twojej funkcji nie jest trywialna, powinieneś użyć słowa kluczowego. Pamiętaj, że niewiele jest do stracenia.

Witaj świecie
źródło