Dlaczego więc właściwie zawsze zaleca się używanie const tak często, jak to możliwe? Wydaje mi się, że używanie const może być bardziej uciążliwe niż pomoc w C ++. Ale z drugiej strony, podchodzę do tego z perspektywy Pythona: jeśli nie chcesz, aby coś zostało zmienione, nie zmieniaj tego. W związku z tym, oto kilka pytań:
Wygląda na to, że za każdym razem, gdy oznaczam coś jako const, pojawia się błąd i muszę gdzieś zmienić inną funkcję, aby też była stała. To powoduje, że muszę zmienić inną funkcję w innym miejscu. Czy to jest coś, co staje się łatwiejsze wraz z doświadczeniem?
Czy korzyści z używania const naprawdę wystarczają, aby zrekompensować kłopoty? Jeśli nie zamierzasz zmieniać obiektu, dlaczego nie napisać kodu, który go nie zmienia?
Powinienem zauważyć, że w tym momencie najbardziej koncentruję się na korzyściach wynikających z używania const do celów poprawności i łatwości konserwacji, chociaż miło jest również mieć pojęcie o implikacjach wydajnościowych.
źródło
const
Odpowiedzi:
To jest ostateczny artykuł o „poprawności const”: https://isocpp.org/wiki/faq/const-correctness .
Krótko mówiąc, używanie const jest dobrą praktyką, ponieważ ...
Kompilator może go zoptymalizować. Na przykład jesteś chroniony przed
if( x = y ) // whoops, meant if( x == y )
Jednocześnie kompilator może generować bardziej wydajny kod, ponieważ przez cały czas dokładnie wie, jaki będzie stan zmiennej / funkcji. Jeśli piszesz zwarty kod C ++, to dobrze.
Masz rację, ponieważ konsekwentne używanie stałej poprawności może być trudne, ale kod końcowy jest bardziej zwięzły i bezpieczniejszy w programowaniu. Kiedy dużo pracujesz nad C ++, korzyści z tego szybko się ujawniają.
źródło
const
zmienne mogą zwiększyć szybkość w tym sensie, że kompilator może wygenerować bardziej optymalny kod, ponieważ zna pełny cel i użycie zmiennej. Czy zauważysz różnicę? Cóż, jest to dyskusyjne w przypadku twojego wniosku. Jeśli chodzi o współbieżność, zmienne const są tylko do odczytu, co oznacza, że nie ma potrzeby blokowania tych zmiennych na wyłączność, ponieważ wartość zawsze będzie taka sama.const
że jest bezpieczna dla wątków, a traktowanie własnego kodu w ten sposób ułatwia sprawdzenie możliwych problemów wielowątkowych i jest łatwym sposobem na zapewnienie gwarancji API dla użytkowników API.Oto fragment kodu z typowym błędem, przed którym może Cię chronić poprawność const:
void foo(const int DEFCON) { if (DEFCON = 1) //< FLAGGED AS COMPILER ERROR! WORLD SAVED! { fire_missiles(); } }
źródło
Z doświadczenia wynika, że to totalny mit. Dzieje się tak, gdy niepoprawny jest stały kod z poprawnym stałym kodem, jasne. Jeśli projektujesz const-correct od samego początku, NIGDY nie powinno to stanowić problemu. Jeśli się coś const, a potem coś innego nie complile, kompilator mówi ci coś niezwykle ważne i należy poświęcić trochę czasu, aby to naprawić poprawnie .
źródło
const
prawidłowo (tj. „od początku”), to rzeczywiście nie byłoby problemu, o co dokładnie chodzi!To nie jest dla Ciebie, kiedy piszesz kod na początku. Jest dla kogoś innego (lub dla Ciebie kilka miesięcy później), który patrzy na deklarację metody wewnątrz klasy lub interfejsu, aby zobaczyć, co robi. Brak modyfikowania obiektu jest istotną informacją, którą można z tego wyciągnąć.
źródło
Jeśli używasz const rygorystycznie, zdziwiłbyś się, jak niewiele rzeczywistych zmiennych występuje w większości funkcji. Często nie więcej niż licznik pętli. Jeśli twój kod osiąga ten punkt, wewnątrz czujesz się ciepło ... sprawdzanie poprawności przez kompilację ... królestwo programowania funkcjonalnego jest blisko ... możesz go teraz prawie dotknąć ...
źródło
const to obietnica, którą składasz jako programista i pozyskuje pomoc kompilatora w egzekwowaniu.
Moje powody, dla których mam stałą poprawność:
źródło
Moja filozofia jest taka, że jeśli masz zamiar używać wymagającego języka z kontrolą czasu kompilacji, to najlepiej go wykorzystaj.
const
to wymuszony przez kompilator sposób komunikowania tego, co masz na myśli ... jest lepszy niż komentarze lub doxygen. Płacisz cenę, dlaczego nie wyliczyć wartości?źródło
Programowanie C ++ bez const jest jak jazda bez zapiętych pasów bezpieczeństwa.
Zapinanie pasa bezpieczeństwa za każdym razem, gdy wchodzisz do samochodu, jest uciążliwe, a 364 z 365 dni bezpiecznie dotrzesz do celu.
Jedyną różnicą jest to, że kiedy będziesz miał kłopoty z samochodem, poczujesz to od razu, podczas gdy przy programowaniu bez const być może będziesz musiał szukać przez dwa tygodnie, co spowodowało tę awarię, tylko po to, aby dowiedzieć się, że nieumyślnie pomieszałeś argument funkcji, który przeszedłeś przez odniesienie non-const dla wydajności.
źródło
W przypadku programowania wbudowanego
const
rozsądne używanie podczas deklarowania globalnych struktur danych może zaoszczędzić dużo pamięci RAM, powodując umieszczanie stałych danych w pamięci ROM lub pamięci flash bez kopiowania do pamięci RAM podczas rozruchu.W codziennym programowaniu
const
ostrożne używanie pomaga uniknąć pisania programów, które ulegają awariom lub zachowują się nieprzewidywalnie, ponieważ próbują modyfikować literały ciągów i inne stałe dane globalne.Podczas pracy z innymi programistami nad dużymi projektami,
const
prawidłowe użycie pomaga zapobiegać dławieniu przez innych programistów.źródło
const
pomaga wyodrębnić kod, który „zmienia rzeczy” za Twoimi plecami. Tak więc w klasie oznaczasz wszystkie metody, które nie zmieniają stanu obiektu, jakoconst
. Oznacza to, żeconst
instancje tej klasy nie będą już mogły wywoływać żadnychconst
metod niebędących metodami. W ten sposób zapobiega się przypadkowemu wywołaniu funkcji, która może zmienić Twój obiekt.Jest również
const
częścią mechanizmu przeciążenia, więc możesz mieć dwie metody z identycznymi podpisami, ale jedną zconst
i jedną bez. Ten, któryconst
maconst
odniesienia, jest wezwany do odwołań, a drugi do brakuconst
odniesień.Przykład:
#include <iostream> class HelloWorld { bool hw_called; public: HelloWorld() : hw_called(false) {} void hw() const { std::cout << "Hello, world! (const)\n"; // hw_called = true; <-- not allowed } void hw() { std::cout << "Hello, world! (non-const)\n"; hw_called = true; } }; int main() { HelloWorld hw; HelloWorld* phw1(&hw); HelloWorld const* phw2(&hw); hw.hw(); // calls non-const version phw1->hw(); // calls non-const version phw2->hw(); // calls const version return 0; }
źródło
Poprawność const jest jedną z tych rzeczy, które naprawdę muszą być wprowadzone od samego początku. Jak już zauważyłeś, dodanie go później jest dużym problemem, zwłaszcza gdy istnieje duża zależność między nowymi funkcjami, które dodajesz, a starymi funkcjami niepoprawnymi do stałej, które już istnieją.
W przypadku dużej części kodu, który piszę, było to naprawdę warte wysiłku, ponieważ często używamy kompozycji:
class A { ... } class B { A m_a; const A& getA() const { return m_a; } };
Gdybyśmy nie mieli stałej poprawności, musiałbyś uciekać się do zwracania złożonych obiektów według wartości, aby upewnić się, że nikt nie manipuluje stanem wewnętrznym klasy B za twoimi plecami.
Krótko mówiąc, stała poprawność jest obronnym mechanizmem programowania, który uchroni Cię przed bólem w przyszłości.
źródło
Powiedzmy, że masz zmienną w Pythonie. Wiesz, że nie powinieneś go modyfikować. A jeśli przypadkowo to zrobisz?
C ++ daje ci sposób na zabezpieczenie się przed przypadkowym zrobieniem czegoś, czego nie powinieneś być w stanie zrobić w pierwszej kolejności. Z technicznego punktu widzenia i tak można to ominąć, ale musisz włożyć dodatkową pracę, aby się zastrzelić.
źródło
Jest ładny artykuł tutaj o const w C ++. To dość prosta opinia, ale mam nadzieję, że niektórym pomoże.
źródło
Używając słowa kluczowego „const”, określasz inny interfejs dla swoich klas. Istnieje interfejs, który zawiera wszystkie metody i interfejs, który zawiera tylko metody const. Oczywiście pozwala to ograniczyć dostęp do niektórych rzeczy, których nie chcesz zmieniać.
Tak, z czasem staje się to łatwiejsze.
źródło
Lubię stałą poprawność ... w teorii. Za każdym razem, gdy próbowałem zastosować go rygorystycznie w praktyce, w końcu się zepsuł i const_cast zaczyna pełzać, czyniąc kod brzydkim.
Może to tylko wzorce projektowe, których używam, ale const zawsze kończy się zbyt szerokim pędzlem.
Na przykład, wyobraź sobie prosty silnik bazy danych ... ma obiekty schematu, tabele, pola itp. Użytkownik może mieć wskaźnik 'const Table', co oznacza, że nie może modyfikować samego schematu tabeli ... ale co z manipulowaniem dane powiązane z tabelą? Jeśli metoda Insert () jest oznaczona jako const, wówczas wewnętrznie musi odrzucić tę stałą, aby faktycznie manipulować bazą danych. Jeśli nie jest oznaczony jako const, nie chroni przed wywołaniem metody AddField.
Być może odpowiedzią jest podzielenie klasy na podstawie wymagań dotyczących ciągłości, ale to zwykle komplikuje projekt bardziej, niż bym chciał ze względu na korzyści, jakie przynosi.
źródło
Możesz również podać wskazówki kompilatora za pomocą const ... zgodnie z poniższym kodem
#include <string> void f(const std::string& s) { } void x( std::string& x) { } void main() { f("blah"); x("blah"); // won't compile... }
źródło