cv
(
const
and
volatile
)
type qualifiers
객체의 선언 또는 명명되는 타입의 constness 또는 volatility를 지정하기 위해, 선언 문법 의 decl-specifier-seq 를 포함한 모든 타입 지정자에 나타납니다.
- const - 해당 타입이 상수(constant) 임을 정의합니다.
- volatile - 해당 타입이 휘발성(volatile) 임을 정의합니다.
목차 |
설명
함수 타입이나 function type 또는 reference type 이 아닌 모든 (아마도 incomplete 인) 타입은 다음 네 가지 구별되지만 관련된 타입 그룹 중 하나에 속합니다:
- cv-unqualified 버전.
- const-qualified 버전.
- volatile-qualified 버전.
- const-volatile-qualified 버전.
동일한 그룹 내의 이 네 가지 유형은 동일한 representation 과 alignment 요구사항을 가집니다.
배열 타입 은 해당 요소 타입과 동일한 cv-qualification을 가진 것으로 간주됩니다.
const 및 volatile 객체
객체가 처음 생성될 때 사용된 cv 한정자들(이는 decl-specifier-seq 의 일부이거나 declarator 의 일부, 또는 선언 에서의 type-id 의 일부, 혹은 new-expression 에서의 type-id 의 일부일 수 있음)는 다음과 같이 객체의 constness 또는 volatility를 결정합니다:
- const 객체 는
-
- const로 한정된 타입의 객체, 또는
- const 객체의 non- mutable 서브객체.
- 이러한 객체는 수정할 수 없습니다: 직접 수정을 시도하는 것은 컴파일 타임 오류를 발생시키며, 간접적으로 수정을 시도하는 경우(예: non-const 타입의 참조자나 포인터를 통해 const 객체를 수정하는 경우) 미정의 동작을 초래합니다.
- volatile 객체 는
-
- volatile로 한정된(qualified) 타입을 가진 객체,
- volatile 객체의 하위 객체(subobject), 또는
- const-volatile 객체의 mutable 하위 객체.
- volatile로 한정된 타입의 glvalue 표현식을 통해 이루어지는 모든 접근(읽기 또는 쓰기 연산, 멤버 함수 호출 등)은 최적화 목적 상 가시적 부작용(visible side-effect)으로 취급됩니다(즉, 단일 실행 스레드 내에서 volatile 접근은 최적화되어 제거되거나 순서가 지정된(sequenced-before) 또는 순서가 뒤따르는(sequenced-after) 다른 가시적 부작용과 재정렬될 수 없습니다). 이로 인해 volatile 객체는 시그널 핸들러(signal handler) 와의 통신에는 적합하지만, 다른 실행 스레드와의 통신에는 적합하지 않습니다( std::memory_order 참조). volatile 객체를 비-volatile 타입의 glvalue (예: 비-volatile 타입에 대한 참조자 또는 포인터)를 통해 접근하려는 모든 시도는 정의되지 않은 동작(undefined behavior)을 초래합니다.
- A const volatile object 는
- const 객체와 volatile 객체 모두로서 동작합니다.
각 cv-한정자( const 와 volatile )는 모든 cv-한정자 시퀀스에서 최대 한 번만 나타날 수 있습니다. 예를 들어, const const 와 volatile const volatile 는 유효한 cv-한정자 시퀀스가 아닙니다.
mutable
지정자
- mutable - 포함 객체가 const로 선언된 경우에도 mutable로 선언된 클래스 멤버의 수정을 허용합니다(즉, 클래스 멤버가 mutable임).
비정적 클래스 멤버 의 비참조 비상수 타입 선언에 나타날 수 있습니다:
class X { mutable const int* p; // 허용됨 mutable int* const q; // 잘못된 형식 mutable int& r; // 잘못된 형식 };
mutable 는 멤버가 클래스의 외부적으로 보이는 상태에 영향을 주지 않음을 지정하는 데 사용됩니다 (뮤텍스, 메모 캐시, 지연 평가, 접근 계측 등에 자주 사용됨).
class ThreadsafeCounter { mutable std::mutex m; // "M&M 규칙": mutable과 mutex는 함께 사용된다 int data = 0; public: int get() const { std::lock_guard<std::mutex> lk(m); return data; } void inc() { std::lock_guard<std::mutex> lk(m); ++data; } };
변환
cv 한정자 간에는 제한이 증가하는 순서로 부분 순서가 존재합니다. 타입은 다음과 비교하여 더 많이 또는 더 적게 cv-qualified 되었다고 말할 수 있습니다:
- 한정되지 않은 < const
- 한정되지 않은 < volatile
- 한정되지 않은 < const volatile
- const < const volatile
- volatile < const volatile
cv 한정 타입에 대한 참조와 포인터는 더 많은 cv 한정 타입에 대한 참조와 포인터로 암시적으로 변환될 수 있습니다. 자세한 내용은 qualification conversions 를 참조하십시오.
cv-한정된 타입의 참조나 포인터를 더 적은 cv-한정을 가진 타입의 참조나 포인터로 변환하려면,
const_cast
를 사용해야 합니다.
참고 사항
const 한정자를 비지역(non-local) 비휘발성(non-volatile) 비템플릿(non- template ) (C++14부터) 비인라인(non- inline ) (C++17부터) 변수 선언에서 사용하고 extern 으로 선언되지 않은 경우, 이 변수에 내부 링크age 를 부여합니다. 이는 C 언어에서 const 파일 범위 변수가 외부 링크age를 가지는 것과 다릅니다.
C++ 언어 문법은 mutable 을 storage-class-specifier 로 처리하지만, 이는 저장 부류(storage class)나 링크(linkage)에 영향을 주지 않습니다.
|
volatile의 일부 사용법이 deprecated 되었습니다:
|
(since C++20) |
키워드
예제
#include <cstdlib> int main() { int n1 = 0; // non-const object const int n2 = 0; // const object int const n3 = 0; // const object (same as n2) volatile int n4 = 0; // volatile object const struct { int n1; mutable int n2; } x = {0, 0}; // const object with mutable member n1 = 1; // OK: modifiable object // n2 = 2; // error: non-modifiable object n4 = 3; // OK: treated as a side-effect // x.n1 = 4; // error: member of a const object is const x.n2 = 4; // OK: mutable member of a const object isn't const const int& r1 = n1; // reference to const bound to non-const object // r1 = 2; // error: attempt to modify through reference to const const_cast<int&>(r1) = 2; // OK: modifies non-const object n1 const int& r2 = n2; // reference to const bound to const object // r2 = 2; // error: attempt to modify through reference to const // const_cast<int&>(r2) = 2; // undefined behavior: attempt to modify const object n2 [](...){}(n3, n4, x, r2); // see also: [[maybe_unused]] std::system("g++ -O3 -Wa,-adhln ./main.cpp"); // may issue asm on POSIX systems }
가능한 출력:
# typical machine code produced on an x86_64 platform
# (only the code that contributes to observable side-effects is emitted)
main:
movl $0, -4(%rsp) # volatile int n4 = 0;
movl $3, -4(%rsp) # n4 = 3;
xorl %eax, %eax # return 0 (implicit)
ret
결함 보고서
다음 동작 변경 결함 보고서는 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| CWG 1428 | C++98 | 'const 객체'의 정의가 선언을 기반으로 함 | 객체 타입을 기반으로 함 |
| CWG 1528 | C++98 |
동일한 cv-qualifier 시퀀스에서 각 cv-qualifier의
발생 횟수에 대한 요구사항이 없었음 |
각 cv-qualifier당
최대 한 번만 허용 |
| CWG 1799 | C++98 |
mutable
이
const
로 선언되지 않은
데이터 멤버에 적용될 수 있었지만, 멤버의 타입이 여전히 const-qualified일 수 있었음 |
const-qualified 타입의 데이터 멤버에는
mutable 을 적용할 수 없음 |
참고 항목
|
C 문서
참조:
const
한정자
|
|
|
C 문서
참조:
volatile
한정자
|