名前空間
変種
操作

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

オブジェクト参照関数 (関数テンプレートの特殊化を含む) およびは、と呼ばれる性質を持ちます。 これは、それらのエンティティに対して許される操作の制限と、ビットの並びに対する意味論上の意味付けの、両方を表します。

目次

[編集] 型の分類

C++の型システムは以下の型から構成されます。

  • bool
  • 文字型
  • ナロー文字型
  • 普通の文字型 (charsigned charunsigned char)
  • char8_t
  • ワイド文字型 (char16_tchar32_twchar_t)
  • 符号付き整数型 (short intintlong intlong long int)
  • 符号なし整数型 (unsigned short intunsigned intunsigned long intunsigned long long int)
  • オブジェクトへの左辺値参照型
  • 関数への左辺値参照型
  • オブジェクトへの右辺値参照型
  • 関数への右辺値参照型

参照と関数以外のすべての型について、その型の3種類の cv 修飾されたバージョン (constvolatileconst volatile) が追加でサポートされます。

型はその性質に基づいて様々なカテゴリに分類されます。

  • オブジェクト型は、関数型でなく、参照型でなく、 void 型でない型 (またはそれらの cv 修飾された型) です (std::is_object も参照してください)。
  • スカラー型は、配列型でなく、クラス型でない、オブジェクト型 (またはそれらの cv 修飾された型) です (std::is_scalar も参照してください)
  • トリビアルな型 (std::is_trivial を参照してください)、 POD 型 (std::is_pod を参照してください)、リテラル型 (std::is_literal_type を参照してください)、およびその他の型は型特性ライブラリに、または名前付き型要件として掲載されています。

[編集] 型の名前付け

名前は以下の方法で型を参照するように宣言できます。

C++プログラム内でしばしば名前を持たない型を参照する必要があります。 そのための構文は type-id と呼ばれます。 型 T を表す type-id の構文は正確に型 T の変数または関数の宣言の構文です。 ただし識別子は省略され、宣言の文法の decl-specifier-seqtype-specifier-seq に制約され、 type-id が非テンプレート型エイリアス宣言の右側に現れる場合にのみ新しい型が定義されます。

int* p;               // int へのポインタの宣言
static_cast<int*>(p); // type-id は「int*」
 
int a[3];   // int 3個の配列の宣言
new int[3]; // type-id は「int[3]」 (new-type-id と呼ばれます)
 
int (*(*x[2])())[3];      // int 3個の配列へのポインタを返す関数への
                          // ポインタ2個の配列の宣言
new (int (*(*[2])())[3]); // type-id は「int (*(*[2])())[3]」
 
void f(int);                    // int を取り void を返す関数の宣言
std::function<void(int)> x = f; // 型テンプレート引数は type-id 「void(int)」
std::function<auto(int) -> void> y = f; // 同上
 
std::vector<int> v;       // int のベクタの宣言
sizeof(std::vector<int>); // type-id は「std::vector<int>」
 
struct { int x; } b;         // 新しい型を作成し、その型のオブジェクト b を宣言
sizeof(struct{ int x; });    // エラー、 sizeof 式の中で新しい型を宣言することはできません
using t = struct { int x; }; // 新しい型を作成し、その型のエイリアスとして t を宣言
 
sizeof(static int); // エラー、 type-specifier-seq の一部でない記憶域クラス指定子
std::function<inline void(int)> f; // エラー、いずれも関数指定子ではありません

宣言の文法から名前を除いた宣言子の部分は抽象宣言子と呼ばれます。

type-id は以下の状況で使用することができます。

type-id は以下の状況で多少変更して使用することができます。

  • 関数の仮引数リストにおいて (引数名が省略されたときに)、 type-id は type-specifier-seq の代わりに decl-specifier-seq を使用します (特に、いくつかの記憶域クラス指定子が使用できます)。
  • ユーザ定義変換関数の名前において、抽象宣言子は関数または配列演算子を含むことができません。

[編集] 複雑型指定子

複雑型指定子は、以前に宣言されたクラス (クラス、構造体、または共用体) の名前、または以前に宣言された列挙の名前を参照するために使用できます (たとえその名前が非型宣言によって隠蔽されている場合であっても)。 これらは新しいクラスの名前を宣言するために使用されることもあります。

詳細については複雑型指定子を参照してください。

[編集] 静的な型

プログラムのコンパイル時の解析の結果である式の型は、その式の静的な型と呼ばれます。 静的な型はプログラムの実行中に変更されません。

[編集] 動的な型

何らかの glvalue 式多相オブジェクトを参照する場合、その最も派生した型は動的な型と呼ばれます。

struct B { virtual ~B() {} }; // 多相型
struct D: B {}; // 多相型
D d; // 最も派生したオブジェクト
B* ptr = &d;
// (*ptr) の静的な型は B です。
// (*ptr) の動的な型は D です。

prvalue 式の場合、動的な型は常に静的な型と同じです。

[編集] 不完全型

以下の型は不完全型です。

  • void 型 (または cv 修飾された void 型)。
  • 宣言されているけれども定義されていないクラス型 (例えば前方宣言によって)。
  • サイズが未知な配列
  • 要素が不完全型の配列。
  • 列挙型の、ベースとなる型がまだ決定していない場所から見た場合。

以下の文脈はいずれもクラス T が完全であることを要求します。

(全般的に、 T のサイズやレイアウトが判明していなければならないときです。)

ある翻訳単位でこれらのいずれかの状況が発生した場合は、その型の定義が同じ翻訳単位内に現れなければなりません。 そうでない場合は、それは要求されません。

不完全に定義されたオブジェクト型は完全にすることができます。

  • クラス型 (class X など) は、翻訳単位内のある地点で不完全であり、その後、完全となることがあります。 型 class X はどちらの地点でも同じ型です。
class X;              // X は不完全型です。
extern X* xp;         // xp は不完全型へのポインタです。
 
void foo() {
  xp++;               // ill-formed、 X は不完全です。
}
 
struct X { int i; };  // ここで X は完全型になります。
 
X x;
void bar() {
  xp = &x;            // OK、型は「X へのポインタ」です。
  xp++;               // OK、 X は完全です。
}
  • 任意のオブジェクトの宣言された型は、不完全なクラスの配列であってもよく、そのため不完全であることがあります。 そのクラス型がその翻訳単位内で後に完全になる場合、その配列型は完全になります。 それら2つの地点におけるその配列型は同じ型です。
  • 配列オブジェクトの宣言された型はサイズが未知な配列であってもよく、そのため翻訳単位内のある地点で不完全であり後に完全となることがあります。 それら2つの地点におけるその配列型 (「境界が未知な T の配列」と「N 個の T の配列」) は異なる型です。
  • 境界が未知な配列または typedef 宣言によって境界が未知な配列と定義された型へのポインタの型は、完全になることはできません。

[編集] 関連項目