C ++에서 휘발성 vs. 가변


85

휘발성과 가변성의 차이점에 대한 질문이 있습니다. 두 가지 모두 변경 될 수 있음을 의미합니다. 또 뭐야? 그들은 같은 것입니까? 차이점이 뭐야? 어디에 적용 할 수 있습니까? 두 가지 아이디어가 제안 된 이유는 무엇입니까? 다른 방법으로 사용하는 방법?

감사합니다.

답변:


112

mutable필드에도 통해 액세스 개체 변경 될 수 const포인터 또는 레퍼런스, 또는의 const컴파일러 R / O 메모리에이를 은닉하지 알고 있으므로, 물체. volatile컴파일러는 값이 "가능성이없는 수 있다는 잘못된 가정하에 그 값의 최적화 예를 들어 등록 할당을하지 인식 할 수 있도록 위치, 컴파일러 (예 : 일부 커널 레벨 드라이버)에 대해 알고하지 않는 코드에 의해 변경 될 수 있습니다 하나입니다 변경됨 "이 해당 레지스터에 마지막으로로드 되었기 때문입니다. 매우 다른 종류의 잘못된 최적화를 중지하기 위해 매우 다른 종류의 정보가 컴파일러에 제공됩니다.


13
volatile객체는 CPU를 전혀 사용하지 않는 프로세스에 의해 변경 될 수도 있습니다. 예를 들어, 통신 주변 장치의 바이트 수신 레지스터는 바이트 수신시 자체적으로 증가 할 수 있으며 이는 인터럽트를 트리거 할 수도 있습니다. 또 다른 예는 주변 장치에서 보류중인 인터럽트 플래그 레지스터입니다.
Mike DeSimone

55
또한 volatile객체가 컴파일러의 지식 밖에서 변경 될 수 있음을 의미 할뿐만 아니라 해당 쓰기가 쓸모없는 것처럼 보이더라도 컴파일러가 객체에 대한 쓰기를 제거 할 수 없음을 의미합니다. 예 : x = 1; x = 0; ifx 휘발성 컴파일러 (하드웨어 수준에서 중요 할 수 있음) 모두 쓰기 작업을 방출한다. 그러나 비 휘발성 객체의 경우 컴파일러는 사용되지 않았으므로 작성하는 데 신경 쓰지 않도록 선택할 수 1있습니다.
마이클 버

15
개체는 constvolatile! 개체를 변경할 수는 없지만 등 뒤에서 변경할 수 있습니다.
CTMacUser

2
@Destructor : 일반적인 상황은 하드웨어 장치 레지스터에 쓰는 것입니다.
Michael Burr

5
@Destructor LED의 상태를 제어한다고 가정 해 보겠습니다. 0 쓰기는 OFF, 1 쓰기는 ON입니다. 일부 오류 상태를 전달하기 위해 LED를 깜박 여야하지만 컴파일러가 마지막 쓰기를 제외한 모든 쓰기를 최적화하기로 결정한 경우 값이 사용되지 않기 때문에 LED가 깜박이지 않고 원하는 동작이 실현되지 않습니다. .
iheanyi

28

mutable: mutable 키워드는 둘러싸는 const 문을 재정의합니다. const 객체의 변경 가능한 멤버는 수정할 수 있습니다.

volatile: volatile 키워드는 컴파일러가 해당 변수를 최적화하지 못하도록하는 변수를 선언 할 때 사용되는 구현 종속 수정 자입니다. Volatile은 컴파일러가 수행 할 수있는 최적화와 충돌 할 수있는 예기치 않은 방식으로 (즉, 인터럽트를 통해) 값이 변경 될 수있는 변수와 함께 사용해야합니다.

출처


당신은 말했다 Volatile should be used with variables whose value can change in unexpected ways우리가 무작위로를 사용하는 것을 선호 하는가?
아시프 Mushtaq

@AsifMushtaq는 값이 아닙니다. 방법. mutable은 작성하는 코드의 권한에 영향을줍니다. 따라서 const ptr 또는 const 참조를 통해 변수에 액세스 할 수 있습니다. 코드가 그것을 변경하지 않는다면 어떨까요? 컴파일러가 ptr 또는 참조 유형을 확인할 수없는 것이 있습니까? 그것은 휘발성입니다. 또한 휘발성은 캐시가 주 메모리에 다시 쓰도록합니다. 따라서 이것은 다중 스레드 코드로 많이 사용됩니다. :)
Dan

22

그들은 확실히 같은 것이 아닙니다. Mutable은 const와 상호 작용합니다. const 포인터가 있으면 일반적으로 멤버를 변경할 수 없습니다. Mutable은 해당 규칙에 예외를 제공합니다.

반면에 휘발성은 프로그램의 변경 사항과는 전혀 관련이 없습니다. 이는 메모리가 컴파일러의 제어를 벗어난 이유로 변경 될 수 있으므로 컴파일러는 매번 메모리 주소를 읽거나 써야하며 레지스터에 콘텐츠를 캐시 할 수 없음을 의미합니다.


"반면에 휘발성은 프로그램에 의한 변경과 전혀 관련이 없습니다 ..." -흠, 멤버를 휘발성으로 만들고 컴파일 중에 중단되는 사항을 확인합니다. 사실 후에 휘발성을 추가하는 것은 사실 뒤에 const를 추가하려는 것과 매우 유사합니다. 고통 스럽습니다.
jww

@jww : 프로그램이 작성한 글과는 전혀 관련이 없습니다. 유형의 객체 주소를 가져 T와서 a에 저장 const T*하고 읽을 수 있습니다. 해당 객체를 만들면 쓰기를 시도하지 않더라도 volatile주소를에 저장할 const T*수 없습니다. volatile프로그램 코드의 변경 / 수정 / 메모리 쓰기는 완전히 직교합니다.
Ben Voigt 2015

17

차이를 조잡하지만 효과적으로 생각하는 방법은 다음과 같습니다.

  • 컴파일러는 변경 가능한 객체가 변경되는시기를 알고 있습니다.
  • 컴파일러는 휘발성 객체가 언제 변경되는지 알 수 없습니다.

1
그 맥락에서 : volatilebytes_received, mutablereference_count.
Mike DeSimone

11

표시된 변수 mutable는 선언 된 메서드에서 수정할 수 있습니다 const.

표시된 변수 volatile는 코드에서 지시 할 때마다 변수를 읽고 써야한다고 컴파일러에 알려줍니다 (즉, 변수에 대한 액세스를 최적화 할 수 없습니다).


4

volatile은 멀티 스레딩 애플리케이션을 다룰 때도 매우 유용합니다. 즉, 메인 스레드 (main ()이있는 곳)가 있고 변수 "app_running"이 참인 동안 계속 회전하는 작업자 스레드를 생성합니다. main ()은 "app_running"이 참인지 거짓인지를 제어하므로 "app_running"선언에 volatile 속성을 추가하지 않으면 컴파일러가 보조 스레드가 실행하는 코드에서 "app_running"에 대한 액세스를 최적화하면 main ( )는 "app_running"을 false로 변경할 수 있지만 값이 캐시되었으므로 보조 스레드는 계속 실행됩니다. Linux 및 VisualC ++에서 gcc를 사용하여 동일한 동작을 보았습니다. "app_running"선언에있는 "volatile"속성이 문제를 해결했습니다. 그래서,


1
아니! 이것은 일반적인 오해입니다. C ++ 11 및 C11은 이러한 목적을 위해 atomics를 도입했습니다. stackoverflow.com/questions/8819095/…
KristianR
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.