名前空間
変種
操作

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

From cppreference.com
< cpp‎ | language
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

宣言されるオブジェクト、または名前を付けられる型の constness または volatility を指定するために、宣言文法decl-specifier-seq を含む任意の型指定子に現れます。

  • const - 型が定数であることを定義します。
  • volatile - 型が揮発性であることを定義します。

目次

[編集] 説明

関数型または参照型以外の任意の(おそらく不完全な)型は、以下の4つの異なるが関連する型のグループに属する型です。

  • cv-unqualified バージョン。
  • const-qualified バージョン。
  • volatile-qualified バージョン。
  • const-volatile-qualified バージョン。

同じグループ内のこれらの4つの型は、同じ表現アライメント要件を持ちます。

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

[編集] const および volatile オブジェクト

オブジェクトが最初に作成されるとき、使用されるcv修飾子(宣言decl-specifier-seqの一部、またはdeclaratorの一部、あるいはnew-expressiontype-idの一部である可能性があります)は、以下のようにオブジェクトのconstnessまたはvolatilityを決定します。

  • 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 オブジェクトの両方として動作します。

各cv修飾子(const および volatile)は、任意のcv修飾子シーケンス内に最大1回しか現れません。例えば、const const および volatile const volatile は有効なcv修飾子シーケンスではありません。

[編集] mutable 指定子

  • mutable - 含まれるオブジェクトがconst宣言されていても、mutable宣言されたクラスメンバの変更を許可します(つまり、クラスメンバは変更可能です)。

非参照非const型の非静的クラスメンバの宣言に現れることがあります。

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

mutable は、メンバーがクラスの外部から見える状態に影響を与えないことを指定するために使用されます(ミューテックス、メモキャッシュ、遅延評価、アクセス計測などでよく使用されます)。

class ThreadsafeCounter
{
    mutable std::mutex m; // The "M&M rule": mutable and mutex go together
    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修飾がされていると言えます。

  • unqualified < const
  • unqualified < volatile
  • unqualified < const volatile
  • const < const volatile
  • volatile < const volatile

cv修飾された型への参照とポインタは、よりcv修飾された型への参照とポインタに暗黙的に変換できます。詳細については、資格変換を参照してください。

cv修飾された型への参照またはポインタを、より少ないcv修飾された型への参照またはポインタに変換するには、const_castを使用する必要があります。

[編集] 注釈

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

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

volatile のいくつかの使用法は非推奨です。

(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修飾子シーケンス内の各cv修飾子について
最大1回
各cv修飾子について
CWG 1799 C++98 mutable は宣言されていないデータメンバーに適用できた
const、しかしそのメンバーの型は依然としてconst修飾されているかもしれない
mutable をデータに適用できない
const修飾された型のメンバー

[編集] 関連項目

C ドキュメント const 修飾子について
C ドキュメント volatile 修飾子について
English 日本語 中文(简体) 中文(繁體)