Często widziałem warunki immutable
i const
używałem zamiennie. Jednak z mojego (niewielkiego) doświadczenia wynika, że te dwie rzeczy bardzo różnią się między sobą „umową”, którą zawierają w kodzie:
Immutable sprawia, że kontrakt, którego ten obiekt się nie zmieni (np. Krotki Python, łańcuchy Java).
Const zawiera umowę, że w zakresie tej zmiennej nie będzie modyfikowana (nie obiecuje żadnych innych wątków, które mogłyby zrobić z obiektem wskazanym w tym okresie, np. Słowo kluczowe C / C ++).
Oczywiście, te dwa nie są równoważne, chyba że język jest jednowątkowy (PHP) lub ma liniowy lub jednoznaczny system pisania (Clean, Mercury, ATS).
Po pierwsze, czy moje rozumienie tych dwóch pojęć jest prawidłowe?
Po drugie, jeśli istnieje różnica, dlaczego są one prawie wyłącznie używane zamiennie?
źródło
const
nie istnieje w każdym języku, a zmienność i niezmienność nie istnieje w każdym języku, więc sprawienie, by ten język był agonistyczny, nie ma zastosowania. Jest on specyficzny dla języka tylko wtedy, gdy te pojęcia mają zastosowanie.Odpowiedzi:
Porozmawiam z C ++, gdzie ta różnica jest najbardziej istotna.
Jak słusznie zauważysz, niezmienny oznacza, że obiekt nie może się w ogóle zmienić po jego utworzeniu. To tworzenie może oczywiście nastąpić w czasie wykonywania, tzn.
const
Obiekt niekoniecznie musi być stałą czasową kompilacji. W C ++ obiekt jest niezmienny, jeśli spełnione są (1) i (2) lub (3):Nie ma zadeklarowanych członków
mutable
zmutowanych przezconst
funkcje członkaZostało zadeklarowane
const
const
funkcje członków nie służąconst_cast
do usuwaniaconst
kwalifikacji w celu mutowania jakichkolwiek członkówMożna jednak również rozważyć modyfikatory dostępu: jeśli operacja mutuje instancję wewnętrznie, ale nie ma wpływu na stan instancji obserwowalny przez jej publiczny interfejs, obiekt jest „logicznie niezmienny”.
Tak więc C ++ zapewnia narzędzia niezbędne do tworzenia niezmiennych obiektów, ale podobnie jak większość wszystkiego w C ++, narzędzia są tylko w minimalnym stopniu wystarczające i wymagają staranności, aby móc ich używać. Stan instancji niekoniecznie ogranicza się do zmiennych składowych instancji - ponieważ C ++ nie zapewnia sposobu wymuszania przejrzystości referencyjnej, może również obejmować stan globalny lub klasowy.
const
ma także inną funkcję w C ++: kwalifikowanie referencji i wskaźników.const
Odniesienia może odnosić się do nie-const
przedmiotu. Używanieconst_cast
do mutowania obiektu za pomocąconst
odwołania jest legalne (choć nie jest to generalnie konieczne lub wskazane) , i tylko wtedy , gdy obiekt ten jest zadeklarowany jako inny niżconst
:I oczywiście mutowanie
const
obiektu jest niezdefiniowane :źródło
Mówiąc w języku Java, gdzie słowo kluczowe „final” oznacza „const”, rozważ:
Oznacza to,
someone
że NIGDY nie może odnosić się do innego obiektu Osoby. Ale nadal możesz zmienić dane osoby poleconej. Na przykładsomeone.setMonthlySalary(10000);
Ale jeśli
someone
byłby to obiekt „niezmienny”, spełniony byłby jeden z następujących warunków: (a) Nie miałbyś metody o nazwiesetMonthlySalary
(b) Wywołanie setMonthlySalary zawsze rzucałoby wyjątek taki jakUnsupportedOperationException
źródło
Niezmienne obiekty to takie, które nie zmieniają stanu po jego utworzeniu. Na przykład;
W tym przykładzie obiekt myComplexStr jest niezmienny, ale nie jest stały, ponieważ jego wartość jest obliczana. I jest niezmienny, ponieważ jest łańcuchem i ma właściwość długości statycznej i nie może się zmienić.
Obiekty Const są zwykle używane do identyfikacji niektórych rzeczywistych stałych, których wartości są znane przed kompilacją, takich jak Pi, „USA”, „StackOverflow.com”, numery portów i tak dalej.
Z tej perspektywy Const różni się od niezmiennych obiektów, ponieważ ich wartości nie są obliczane przez program.
Ale jeśli mówisz o słowie kluczowym „const” w C ++, możesz powiedzieć, że „const” służy do tworzenia niezmiennych obiektów.
źródło
const
tego typu jest niezdefiniowanym zachowaniem bez względu na to, gdzie jest przydzielone, IIRC. Nieokreślone zachowanie jest gorsze niż jakikolwiek konkretny błąd, który może się zdarzyć. Oznacza to, że nie używasz już C ++ - C ++ nie zapewnia możliwości zmianyconst
wartości (z wyjątkiemmutable
członków, ale nie o to ci chodzi), więc jeśli chodzi o C ++, nie możesz tego zrobić. To, co konkretne implementacje pozwalają, to zupełnie inna sprawa (i założę się, że jeśli skompilujesz z optymalizacjami, wyczyn, który wykonałeś, nie wpłynie na późniejsze wyrażenia,pi
ponieważ został zastąpiony).Tak, ale twoje drugie pytanie pokazuje, że nie rozumiesz tych różnic.
const
w C ++ jest używany tylko dla poziomu dostępu (oznacza „tylko do odczytu”) , a nie dla niezmienności. Oznacza to, że sam dostęp jest całkowicie oddzielony od danych. Na przykład możesz manipulować niektórymi danymi, a następnie ujawnić je za pomocą stałego odwołania. Dostęp jest tylko do odczytu, ale same dane, ponieważ cały datam jest zmienny.const tylko ograniczenia dostępu gwarantowane, podczas gdy niezmienność (jak na przykład w D) nie implikuje naprawdę żadnego sposobu zmiany danych na dowolnym etapie życia obiektu .
Teraz możesz symulować niezmienność w C ++, upewniając się, że dostęp do niektórych danych nie jest możliwy w żaden inny sposób niż const, i upewnij się, że jest on inicjowany, a następnie nie dotykany. Ale to nie jest silna gwarancja, ponieważ języki takie jak D dają ci, gdy oznaczysz swoje dane jako niezmienne. Język upewnia się, że nie można w ogóle wykonać żadnej operacji modyfikującej te dane, podczas gdy w C ++ nadal jesteś w stanie potencjalnie zmienić dane poprzez rzutowanie i modyfikowanie, jeśli jest to naprawdę konieczne.
Ostatecznie nie jest wcale taki sam, ponieważ nie oferuje takich samych gwarancji.
źródło
Mówiąc o JavaScript, słowach kluczowych
const
iObject.freeze
const
dotyczy powiązańvariables
. Tworzy niezmienne wiązanie, nie można mu przypisać nowej wartości.Object.freeze
działa na wartościach obiektów. Sprawia, że obiekt jest niezmienny . Mianowicie nie można zmienić jego właściwości.źródło
W C ++ są takie same. Chociaż możesz zmienić
const
obiekt, jeśli masz jego lokalizację w pamięci i pozwolenie systemu operacyjnego na zapis do tej pamięci.źródło
W językach C, C ++ i pokrewnych istnieje również różnica między obiektem będącym stałym a odniesieniem lub wskaźnikiem do obiektu będącego stałym odniesieniem.
Jeśli spróbujesz zmodyfikować stały obiekt, otrzymasz niezdefiniowane zachowanie. (Możesz spróbować zmodyfikować stały obiekt, na przykład biorąc jego adres, rzutując adres na wskaźnik nie będący const, a następnie używając tego wskaźnika non-const do modyfikacji obiektu).
Z drugiej strony stały wskaźnik lub odniesienie informuje kompilator, że nie można użyć tego wskaźnika lub odniesienia do modyfikacji obiektu. Możesz rzucić wskaźnik lub odwołanie i spróbować zmodyfikować obiekt. Jeśli sam obiekt był stały, zdarzałyby się złe rzeczy. Jeśli obiekt nie był faktycznie stały, zmieni się. Może to oczywiście mylić użytkowników twojego kodu i być może powodować błędy.
W C, jeśli użyjesz literału łańcuchowego, takiego jak „Hello”, pięć znaków i końcowe bajty zerowe są w rzeczywistości stałe, ale otrzymujesz wskaźnik non-const. Bardzo zły pomysł, aby użyć tego nie-stałego wskaźnika do zmiany obiektu.
W C możesz mieć wskaźnik „const ograniczać”. Oznacza to, że wskazany obiekt jest tymczasowo stały. Jeśli obiekt zostanie zmodyfikowany w jakikolwiek sposób, gdy wskaźnik „const ograniczy” znajduje się w zasięgu, zachowanie jest niezdefiniowane. Jest to silniejsze niż wskaźnik const, który tylko uniemożliwia zmianę obiektu za pomocą tego wskaźnika.
źródło