mutable
Pole może być zmieniony nawet w obiekcie dostęp za pomocą const
wskaźnika lub odniesienia, lub w const
obiekcie, więc kompilator nie wie, aby schować go w pamięci R / O. volatile
Lokalizacja to taki, który może zostać zmieniony za pomocą kodu kompilator nie zna (np jakiegoś kierowcy na poziomie jądra), więc kompilator nie wie, aby zoptymalizować np zarejestruj przypisanie tej wartości pod nieprawidłowym założeniu, że wartość „nie może ewentualnie mieć zmieniony "od ostatniego załadowania do tego rejestru. Kompilator otrzymuje bardzo różne informacje w celu zatrzymania różnego rodzaju nieprawidłowych optymalizacji.
volatile
obiekty mogą być również zmieniane przez procesy w ogóle nie angażujące procesora. Na przykład rejestr odebrany przez bajty w urządzeniu peryferyjnym komunikacyjnym może się zwiększać po odebraniu bajtu (a to może nawet wywołać przerwanie). Innym przykładem jest rejestr flagi oczekujących przerwań w urządzeniu peryferyjnym.volatile
nie tylko oznacza, że obiekt może zmienić poza wiedzą kompilatora - oznacza to również, że zapisy do obiektu nie mogą być wyeliminowane przez kompilator nawet jeśli te zapisy pojawiają się bezużyteczne. Na przykład:x = 1; x = 0;
jeślix
jest ulotny, kompilator musi emitować obie operacje zapisu (co może być istotne na poziomie sprzętu). Jednak w przypadku nieulotnego obiektu kompilator może nie zawracać sobie głowy pisaniem,1
ponieważ nigdy nie jest używany.const
ivolatile
! Nie możesz zmienić obiektu, ale możesz go zmienić za plecami.mutable
: Słowo kluczowe mutable przesłania każdą otaczającą instrukcję const. Zmienny element członkowski obiektu const można modyfikować.volatile
: Słowo kluczowe volatile jest modyfikatorem zależnym od implementacji, używanym podczas deklarowania zmiennych, co uniemożliwia kompilatorowi optymalizację tych zmiennych. Volatile powinno być używane ze zmiennymi, których wartość może zmienić się w nieoczekiwany sposób (np. Przez przerwanie), co może kolidować z optymalizacjami, które może wykonać kompilator.Źródło
źródło
Volatile should be used with variables whose value can change in unexpected ways
czy wolimy używać go z przypadkowym?Zdecydowanie NIE są tym samym. Mutable współdziała z const. Jeśli masz wskaźnik do stałej, normalnie nie możesz zmieniać członków. Mutable stanowi wyjątek od tej reguły.
Z drugiej strony zmienność jest całkowicie niezwiązana ze zmianami wprowadzonymi przez program. Oznacza to, że pamięć może się zmienić z przyczyn niezależnych od kompilatora, dlatego kompilator musi za każdym razem odczytywać lub zapisywać adres pamięci i nie może buforować zawartości w rejestrze.
źródło
T
i zapisać go w aconst T*
i odczytać z niego. Jeśli utworzysz ten obiektvolatile
, zapisanie jego adresu wconst T*
nie powiedzie się, nawet jeśli nigdy nie próbujesz pisać.volatile
a zmiany / modyfikacje / zapisy do pamięci z kodu programu są całkowicie ortogonalne.Prosty, ale skuteczny sposób myślenia o różnicy to:
źródło
volatile
bytes_received,mutable
reference_count.Zaznaczona zmienna
mutable
pozwala na jej modyfikację w zadeklarowanej metodzieconst
.Zmienna oznaczona
volatile
mówi kompilatorowi, że musi odczytywać / zapisywać zmienną za każdym razem, gdy Twój kod również o tym mówi (tj. Nie może zoptymalizować dostępu do zmiennej).źródło
Chciałbym dodać, że nietrwałość jest również bardzo przydatna w przypadku aplikacji wielowątkowych, tj. Masz swój główny wątek (w którym żyje main ()) i tworzysz wątek roboczy, który będzie się obracał, gdy zmienna „app_running” jest prawdziwa. main () kontroluje, czy „app_running” jest prawdą czy fałszem, więc jeśli nie dodasz atrybutu volatile do deklaracji „app_running”, jeśli kompilator optymalizuje dostęp do „app_running” w kodzie uruchamianym przez wątek dodatkowy, main ( ) może zmienić „app_running” na false, ale wątek pomocniczy będzie nadal działał, ponieważ wartość została zapisana w pamięci podręcznej. Widziałem to samo zachowanie przy użyciu gcc w systemie Linux i VisualC ++. Atrybut „volatile” umieszczony w deklaracji „app_running” rozwiązał problem. Więc,
źródło