nietrwałe i zmienne w C ++

85

Mam pytanie o różnicę między zmiennymi a zmiennymi. Zauważyłem, że oba oznaczają, że można to zmienić. Co jeszcze? Czy są tym samym? Co za różnica? Gdzie mają zastosowanie? Dlaczego zaproponowano te dwa pomysły? Jak ich używać w inny sposób?

Wielkie dzięki.

skydoor
źródło

Odpowiedzi:

112

mutablePole może być zmieniony nawet w obiekcie dostęp za pomocą constwskaźnika lub odniesienia, lub w constobiekcie, więc kompilator nie wie, aby schować go w pamięci R / O. volatileLokalizacja 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.

Alex Martelli
źródło
13
volatileobiekty 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.
Mike DeSimone
55
Ponadto, volatilenie 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śli xjest 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, 1ponieważ nigdy nie jest używany.
Michael Burr
15
Obiekt można oznaczyć zarówno consti volatile! Nie możesz zmienić obiektu, ale możesz go zmienić za plecami.
CTMacUser
2
@Destructor: typowa sytuacja dotyczy zapisów do rejestru urządzenia sprzętowego.
Michael Burr
5
@Destructor, powiedzmy, że kontrolujesz stan diody LED. Zapis 0 wyłącza, zapis 1 włącza. Jeśli muszę migać diodą LED, aby zakomunikować stan błędu, ale kompilator zdecyduje się zoptymalizować wszystkie zapisy z wyjątkiem ostatniego, ponieważ żadna z wartości nie jest używana, wówczas dioda LED nigdy nie miga, a pożądane zachowanie nie jest realizowane .
iheanyi
28

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

Xian
źródło
powiedziałeś, Volatile should be used with variables whose value can change in unexpected waysczy wolimy używać go z przypadkowym?
Asif Mushtaq
@AsifMushtaq nie wartości. sposoby. zmienna wpływa na uprawnienia, które ma napisany kod. Możesz więc uzyskać dostęp do zmiennej za pomocą const ptr lub odwołania do const. A jeśli to nie twój kod go zmieni? Coś, czego kompilator nie może sprawdzić typu ptr lub referencji? To niestabilne. Nietrwałość wymusza również zapis z pamięci podręcznej z powrotem do pamięci głównej. Więc to jest używane DUŻO z kodem wielowątkowym. :)
Dan
22

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.

Ben Voigt
źródło
„Z drugiej strony niestabilność jest całkowicie niezwiązana ze zmianami wprowadzonymi przez program…” - hmmm, spraw, aby element członkowski był zmienny i zobacz, co się psuje podczas kompilacji. Próba dodania zmiennego po fakcie jest bardzo podobna do próby dodania stałej po fakcie ... Bolesne.
jww
@jww: To zupełnie nie ma związku z zapisami wykonanymi przez program. Możesz wziąć adres obiektu typu Ti zapisać go w a const T*i odczytać z niego. Jeśli utworzysz ten obiekt volatile, zapisanie jego adresu w const T*nie powiedzie się, nawet jeśli nigdy nie próbujesz pisać. volatilea zmiany / modyfikacje / zapisy do pamięci z kodu programu są całkowicie ortogonalne.
Ben Voigt
17

Prosty, ale skuteczny sposób myślenia o różnicy to:

  • Kompilator wie, kiedy zmienia się zmienny obiekt.
  • Kompilator nie może wiedzieć, kiedy zmienny obiekt ulega zmianie.
Jonathan Leffler
źródło
1
W tym duchu: volatilebytes_received, mutablereference_count.
Mike DeSimone
11

Zaznaczona zmienna mutablepozwala na jej modyfikację w zadeklarowanej metodzie const.

Zmienna oznaczona volatilemó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).

Kyle Lutz
źródło
4

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,

BinCoder
źródło
1
Nie! To powszechne nieporozumienie. C ++ 11 i C11 wprowadziły atomics do tego celu stackoverflow.com/questions/8819095/ ...
KristianR