Namespaces
Variants

cv ( const and volatile ) type qualifiers

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
const / volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

객체의 선언 또는 명명되는 타입의 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로 한정된(qualified) 타입을 가진 객체,
  • const volatile 객체의 non- mutable 서브객체,
  • volatile 객체의 const 서브객체, 또는
  • const 객체의 non- mutable volatile 서브객체.
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)

키워드

const , volatile , mutable

예제

#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 한정자