名前空間
変種
操作

cv (const および volatile) 型修飾子

提供: cppreference.com
< cpp‎ | language
 
 
C++言語
一般的なトピック
フロー制御
条件付き実行文
繰り返し文 (ループ)
ジャンプ文
関数
関数宣言
ラムダ関数宣言
inline 指定子
例外指定 (C++20未満)
noexcept 指定子 (C++11)
例外
名前空間
指定子
decltype (C++11)
auto (C++11)
alignas (C++11)
const/volatile
constexpr (C++11)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点
文字 - 文字列 - nullptr (C++11)
ユーザ定義 (C++11)
ユーティリティ
属性 (C++11)
typedef 宣言
型エイリアス宣言 (C++11)
キャスト
暗黙の変換 - 明示的な変換
static_cast - dynamic_cast
const_cast - reinterpret_cast
メモリ確保
クラス
クラス固有の関数特性
特別なメンバ関数
テンプレート
その他
 
 

宣言されているオブジェクトまたは表されている型の定数性や揮発性を指定するために、型指定子 (宣言の文法decl-specifier-seq を含む) 内に現れます。

  • const ー 型が定数であると定義します。
  • volatile ー 型が揮発であると定義します。

目次

[編集] 説明

関数型または参照型以外の任意の型 T (不完全型を含む) について、さらに3つの異なる型 (const 修飾された T、 volatile 修飾された T、 const volatile 修飾された T) が C++ の型システムに存在します。

ノート: 配列型はその要素の型と同じ cv 修飾を持つとみなされます。

オブジェクトが最初に作成されたとき、使用された cv 修飾 (宣言decl-specifier-seq または declarator の一部、または new 式type-id の一部として指定できます) は、以下のように、そのオブジェクトの定数性や揮発性を決定します。

  • const オブジェクト ー const 修飾された型のオブジェクト、または const オブジェクトの mutable でない部分オブジェクト。 そのようなオブジェクトは変更できません。 直接変更する試みはコンパイル時エ���ーであり、間接的に変更する (例えば非 const 型への参照やポインタを通して const オブジェクトを変更する) 試みは未定義動作です。
  • volatile オブジェクト ー volatile 修飾された型のオブジェクト、または volatile オブジェクトの部分オブジェクト、または const volatile オブジェクトの mutable な部分オブジェクト。 volatile 修飾された型の glvalue 式を通して行われたすべてのアクセス (読み書き操作、メンバ関数呼び出しなど) は、最適化の目的に対して可視な副作用として扱われます (つまり、単一の実行のスレッド内では、 volatile アクセスを最適化で除去したり、その volatile アクセスに対して先行配列または後続配列される別の可視な副作用と並び替えたりすることはできません。 これにより、 volatile オブジェクトはシグナルハンドラとの通信に適することとなりますが、別の実行のスレッドとの通信には適しません。 std::memory_order を参照してください)。 非 volatile な glvalue (非 volatile 型への参照やポインタなど) を通して volatile オブジェクトを参照する試みは未定義動作です。
  • const volatile オブジェクト ー const volatile 修飾された型のオブジェクト、 const volatile オブジェクトの mutable でない部分オブジェクト、 volatile オブジェクトの const な部分オブジェクト、または const オブジェクトの mutable でない volatile な部分オブジェクト。 const オブジェクトと volatile オブジェクトの両方として振る舞います。

[編集] mutable 指定子

  • mutable ー たとえ含まれているオブジェクトが const 宣言されていても、 mutable 宣言されたクラスメンバの変更は許容します。

参照でなく const でない非静的クラスメンバの宣言に現れることができます。

class X {
  mutable const int* p;         // OK
  mutable int* const q;         // ill-formed
};

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 修飾されていると言うことができます。

  • 無修飾 < const
  • 無修飾 < volatile
  • 無修飾 < const volatile
  • const < const volatile
  • volatile < const volatile

cv 修飾された型への参照またはポインタは、より多く cv 修飾されている型への参照またはポインタに暗黙に変換されます。 特に、以下の変換が許容されます。

  • 無修飾な型への参照またはポインタは const な型への参照またはポインタに変換できます。
  • 無修飾な型への参照またはポインタは volatile な型への参照またはポインタに変換できます。
  • 無修飾な型への参照またはポインタは const volatile な型への参照やポインタに変換できます。
  • const な型への参照またはポインタは const volatile な型への参照またはポインタに変換できます。
  • volatile な型への参照またはポインタは const volatile な型への参照またはポインタに変換できます。
ノート: 複数段のポインタには追加の制約が課されます。

cv 修飾された型への参照またはポインタをより少なく cv 修飾された型への参照またはポインタに変換するには、 const_cast を使用しなければなりません。

[編集] キーワード

const, volatile, mutable

[編集] ノート

extern 宣言されていない非ローカル、非 volatile、非テンプレート (C++14以上)、非インライン (C++17以上)な変数の宣言に使用される const 修飾子は、その変数に内部リンケージを与えます。 これは const なファイルスコープの変数が外部リンケージ持つ C とは異なります。

C++ の言語の文法では、 mutable は型指定子ではなく記憶域クラス指定子として扱っていますが、記憶域クラスやリンケージには影響しません。

[編集]

int main()
{
    int n1 = 0;           // 非 const オブジェクト
    const int n2 = 0;     // const オブジェクト
    int const n3 = 0;     // const オブジェクト (n2 と同じ)
    volatile int n4 = 0;  // volatile オブジェクト
    const struct
    {
        int n1;
        mutable int n2;
    } x = {0, 0};      // mutable メンバを持つ const オブジェクト
 
    n1 = 1; // OK、変更可能なオブジェクト
//  n2 = 2; // エラー、変更可能でないオブジェクト
    n4 = 3; // OK、副作用として扱われます
//  x.n1 = 4; // エラー、 const オブジェクトのメンバは const です
    x.n2 = 4; // OK、 const オブジェクトの mutable メンバは const ではありません
 
    const int& r1 = n1; // 非 const オブジェクトに束縛された const への参照
//  r1 = 2; // エラー、 const への参照を通して変更しようとしています
    const_cast<int&>(r1) = 2; // OK、非 const オブジェクト n1 を変更します
 
    const int& r2 = n2; // const オブジェクトに束縛された const への参照
//  r2 = 2; // エラー、 const への参照を通して変更しようとしています
//  const_cast<int&>(r2) = 2; // 未定義動作、 const オブジェクト n2 を変更しようとしています
}

出力:

# x86_64 プラットフォーム上で生成される一般的な機械語コード
# (観察可能な副作用に寄与するコードのみが生成されます)
main:
    movl    $0, -4(%rsp) # volatile int n4 = 0;
    movl    $3, -4(%rsp) # n4 = 3;
    xorl    %eax, %eax   # return 0 (暗黙)
    ret

[編集] 関連項目

const 修飾子C言語リファレンス
volatile 修飾子C言語リファレンス