キーワード (C++)本記事では、プログラミング言語C++におけるキーワードについて解説する。 本記事は、あくまでC++のキーワードに焦点をあてた記事であり、C++の全体像や、C++のキーワード以外の面には立ち入らない。読者の理解の助けとなる場合は適宜、他のプログラミング言語と比較する説明は行う。 なおC++のものに限らず、キーワード(keywords)、予約語(reserved words)、予約済みの識別子(reserved identifiers)といった概念全般や細かな違いについては「予約語」の記事を参照のこと。 C++のキーワードの特徴最初に制定された規格であるISO/IEC 14882:1998(通称C++98)では63個のキーワードと11個の代替表現(alternative representations)が採用され、ISO/IEC 14882:2003(通称C++03)では追加のキーワードはなかった。ISO/IEC 14882:2011(通称C++11)で新たに13個のキーワードおよび2個の文脈依存キーワード(後述)が追加された。C++11から追加のキーワードおよび機能には(*)を付す。C++14およびC++17ではキーワードは増えていない。 C言語のC89/C90で存在したキーワードは、すべてがほぼそのままの形で取り入れられている。C95で追加された 値に関するキーワードnullptr (*)ヌルポインタ (null pointer) を表す。この値はある 型に関するキーワード複数のキーワードを組み合わせることで意味が変わるものが多い(文脈依存のキーワード)。 基本型int, long, short, signed, unsigned→詳細は「整数型」を参照
float, double→詳細は「浮動小数点数」を参照
bool, true, false→詳細は「ブーリアン型 § C++」を参照
C99ではマクロで定義されており[注釈 2]キーワードではないが、C++ではキーワードである。 char, wchar_t, char16_t (*), char32_t (*)→詳細は「キャラクタ (コンピュータ)」および「ワイド文字」を参照
void→詳細は「void (コンピュータ)」を参照
auto (*)変数宣言の際に型として指定すると、初期化式から型推論を行う。 また、戻り値型を後置きする関数宣言に用いる。 // 以下の2つは同じ宣言。
int main(int argc, char** argv);
auto main(int argc, char** argv) -> int;
複合型class, struct, unionC++において
なお、C++規格では、クラス内で宣言した変数および関数は、それぞれデータメンバ(data member)およびメンバ関数(member function)と呼ぶ[注釈 3]。データメンバはメンバ変数と呼ばれることも多い。JavaやC#のように、フィールド・メソッドなどといった用語は使われない。 enum→詳細は「列挙型」を参照
型修飾子const→詳細は「const」を参照
Cの書き換え不能という意味に加え、定数の意味が加わっている。具体的にはCと違いブロックスコープにない場合、定数扱いとなり、externを指定しない限り内部結合になる。プリプロセッサによるマクロの代替的手段になる。 const int N = 16;
int Array[N];
このコード片で、Cでは volatile→詳細は「volatile」を参照
volatileの指定された記憶領域は、実行しているコードが書き換えを行わない場合にも、何らかの理由で内容が書き換えられる可能性を持つ。書き換えの起きる具体的な要因としては、何らかのハードウェアによる書き換えが挙げられる。 コンパイラによる最適化では、メモリを書き換えない限り内容が変わらないことを利用し、メモリからの再読み込みの省略などを行うが、例えばあるメモリ領域にハードウェアが書き込んでいて、そのメモリ領域の変化を読み取りループで監視しようとするならば、volatile指定が無い場合はコンパイラが「書き込みを行っていないのでメモリ内容が変化する可能性は無い」と判断し、ループを消し去ったり、メモリを再読み込みせずに単純な無限ループを行ったりするなど、期待と異なる最適化を行う可能性が高い。そのような場合、volatileを適切に指定することで、メモリ領域を正しくポーリングすることが期待できる。 また、コンパイラによっては、volatileの指定された記憶領域へのアクセス前後において、適切なメモリバリアを自動的に配置することもある。が、逆にメモリバリアについては一切関知しないものもあるため、ノンブロッキング同期プログラミングなどでは特別な注意が必要となる。 ハードウェアに近い操作を行う処理を記述する際は、特に重要になる修飾子である。 記憶クラス指定子→「ブロック (プログラミング)」および「スコープ (プログラミング)」も参照
auto (C++03まで)C++03以前では自動変数 (automatic variable) を意味する記憶クラス指定子 (storage class specifier)[5] であったが、C++11で廃止され、型推論のための全く別の機能が割り当てられた。 もともと、関数のようなブロックスコープ内の変数(ローカル変数)に記憶クラスを指定しなかった場合はデフォルトで自動記憶域期間 (automatic storage duration) を持つ自動変数となるため、C++03以前においても記憶クラス指定子としての externCからの外部結合の指定に加え、リンケージ指定の用法が加わっている。 C++では名前(関数名や変数名など)に対して多重定義や名前空間、型安全の保証などの都合から、多くのコンパイラは名前修飾を施しCとは異なった名前をリンカに対して用いている。その名前の修飾の仕方を指定するのがリンケージ指定である。少なくとも"C"と"C++"の2種類のリンケージが使用できる。何も指定しないと"C++"になる。"C"リンケージでは名前の変形を抑止しCと互換の名前をリンカに対して用いることを意味する。これによりCとC++を混在させてプログラムを作るときに使われる。 //a.cpp
extern "C" {
int a; //Cリンケージの変数定義
extern int b; //Cリンケージの変数宣言
void f(); //Cリンケージの関数宣言
}
extern "C" int c; //リンケージ指定と元々の外部結合の意味を兼ねた用法。
//b.c
extern int a; //変数の宣言
int b; //変数の定義
int c;
void f()
{
/* ... */
}
また、 registerC++17以降では何の機能もないキーワードである。将来のために予約されている。 C++14以前では、特にレジスタに割り当ててほしい自動変数に指定する記憶クラス指定子であった。Cよりも意味合いが弱く、Cのregister変数はアドレス参照( static
特にクラスの場合、これは宣言となるため普通のグローバル変数などと同様にソースファイルで定義が必要である。ただし次の場合、例外として不要である。
// ヘッダbar.h
class bar
{
static int a; // OK: 静的メンバ a の宣言。
static const int b = 5; // OK: 静的メンバ b の宣言と定義。クラススコープの定数となる。
static const double c; // OK: 静的メンバ c の宣言。
// static const double d = 2.0; // Bad: 整数型でない。
static void f(); // OK: 静的メンバ f の宣言。
static void g() { /* ... */ } // OK: 静的メンバ g の宣言と定義。
};
// ソースbar.cpp
#include "bar.h"
int bar::a = 1; // OK: bar::a の定義。
//const int bar::b = 5; // クラススコープの定数は定義する必要がない。
const double bar::c = 3.0; // OK: bar::c の定義。
void bar::f() // OK: bar::f の定義。
{
/* ... */
}
古いC++処理系では整数型を C++11以降は mutable
thread_local (*)グローバル変数やクラス・関数内静的変数について、スレッドローカルな記憶域に確保するよう指示する。 宣言指定子friendフレンド関数・フレンドクラスの宣言に用いる。 typedef→詳細は「typedef」を参照
関数指定子constexpr (*)定数式を表す。変数や関数を修飾して、コンパイル時定数となりうることを指示する。 explicitinline
virtual
クラスに関するキーワードアクセス制御public, protected, privateクラスメンバと継承のアクセス制御に用いられる。
Javaなどとは違い個々の宣言に付けるものではなく、見た目には関数内でラベルを指定するのと似ている。1度指定すると他の指定がなされるか、クラスの宣言が終わるまでは指定した制御が続く。 class foo
{
int n; //classであり、まだアクセス制御が指定されていないのでprivateになる
public:
foo(int); //コンストラクタ
~foo(); //デストラクタ
int getN(); //メンバ関数
//ここまでの3つはすべてpublicになる
protected:
void setN(int); //protectedになる
}; //クラス宣言の終わりには ; が必要。
class hoge : private foo //private継承 外部からはhogeのインスタンスを通じてfooのメンバにはアクセスできない。
{
public:
using foo::getN; //このように個別にアクセス制御を上書きすることもできる。
hoge();
~hoge();
};
その他operator
this→「this (プログラミング)」も参照
自分自身へのポインタ。当然ながらクラスの非静的メンバ関数内でのみ使用できる。参照でなくポインタである理由は、thisがC++に導入された当時まだ参照がなかったからである[7]。 文に関するキーワード制御構造→「制御構造」も参照
if, else→詳細は「if文」を参照
for→詳細は「for文」を参照
while, doswitch, case, default→詳細は「switch文」を参照
defaultは関数の定義にも用いる。特殊メンバ関数を「 break→詳細は「break文」を参照
continue→詳細は「continue文」を参照
goto→詳細は「goto文」を参照
return→詳細は「return文」を参照
try, catch→詳細は「例外処理」を参照
式に関するキーワード動的記憶域確保new, delete
deleteは関数の定義にも使用される。関数を「 型変換型変換(キャスト)は注意を要する操作であるにもかかわらず、Cの型変換演算子はあまりにも目立たず、目的がコードから見えにくいという理由からC++では、型変換を行う場合には用途ごとの4つの型変換演算子を用いることが推奨されている。 dynamic_cast動的キャスト。RTTIを用いて、目的の型に変換できるかどうかを確認し、不可能であればポインタの場合ヌルポインタを返し、参照の場合は static_cast静的キャスト。コンパイル時に型チェックを行う。変換前の型から変換後の型へ、あるいはその逆向きの暗黙の変換が存在する場合に変換可能である。変換できなければコンパイルエラーになる。 const_castconst/volatile性を取り除く場合に用いるキャストである。他のキャストでconst/volatile性が失われる変換はできない。 reinterpret_cast安全でなかったり移植性のない型変換に用いる。無関係なポインタ型同士の変換や、ポインタと整数型の変換などがそうである。 式に関する情報alignof (*)型のアライメントの値を得る。 decltype (*)式から型を取得し、型名として用いる。 sizeof型、あるいは式の型のサイズを得る。 →詳細は「sizeof」を参照
また、 typeid→詳細は「RTTI」を参照
例外処理throw→詳細は「例外処理」を参照
例外を投げる。また、後述の例外指定の用法もある(C++11以降でこの用法は非推奨)。 noexcept (*)関数に例外指定を付与する。 //noexceptはどんな例外も投げないことを示す。
int func2() noexcept;
//noexceptはコンパイル時定数となる引数を取ることができ、trueならnoexceptと同じ。
int func3() noexcept(true);
//falseならあらゆる例外を投げる可能性がある。
int func4() noexcept(false);
//noexceptと等価な記述。
int func5() throw();
//noexcept(false)と等価な記述。
int func6() throw(...);
//この関数から投げられる例外はstd::exception型(とその派生クラス型)かint型しかありえないことを示す。この用法は非推奨。
int func7() throw(std::exception, int) {/* ... */}
C++11以降は、throwを用いた例外指定は推奨されない。C++03以前でも、throwを用いた例外指定は例外安全のうち例外を投げない表明としてfunc5のように型を無指定にして用いられる場合が大半であった。 また、noexceptは例外指定の有無を判定する式としても用いられる。 //b2はtrue
bool b2 = noexcept(func2()+1);
//b4はfalse
bool b4 = noexcept(func4()+func7());
表明static_assert (*)コンパイル時に評価される表明を記述する。検査式が偽になると、指定されたメッセージを伴ってコンパイルエラーとなる。宣言として扱われるが、プログラムの動作には影響がない。 static_assert(sizeof(Foo) == 4, "Unexpected: the size of Foo must be 4");
テンプレートに関するキーワード→「テンプレート (プログラミング)」も参照
template
typename
//typenameの例
template <typename T> struct s1 //1の用法
{
void f() {
typename T::type *ptr; //2の用法
}
};
用法2.はなぜ存在するのかというと、曖昧性が生じさせないためである。 たとえばs1に次のようなクラスをテンプレート引数に渡すとする。 struct s2
{
static const int type = 0;
};
すると、仮にtypenameがなければs1<s2>::fの中の文はs2::type *ptr;となる。これはs2::typeとptrの乗算式と見られるので、構文としては正当なC++の式となってしまう(ただしこの例ではptrが宣言されていないためコンパイルエラーになる)。そうならないように、曖昧性を排除するために型名である場合はtypenameを先行させる仕様になっている。 exportC++11では何の機能もないキーワードである。将来のために予約されている(*)。 C++03以前では、分離コンパイルを行うクラス・関数テンプレートに指定するものであった。分離コンパイルとは、通常の関数などのようにヘッダに宣言を書いて、どこかのソースファイルに定義を書く形式のことである。これを指定しないとテンプレートは通常ヘッダに定義を書く必要がある。 このキーワードに対応しているコンパイラは、一般に広く知られたものではComeau C++のみである[8]。対応しない多くのコンパイラでは、このキーワードは単に無視されるか、キーワードとして扱われない場合さえある。 名前空間に関するキーワードnamespace
using
インラインアセンブラasm
アトリビュートalignas (*)変数宣言を修飾するアトリビュートで、変数のアライメントを指定する。 文脈依存のキーワード(*)文脈依存のキーワード(contextual keyword)は、ソースコード中の特定の位置に現れた場合にのみキーワードとして扱われ、それ以外の箇所では単なる識別子として扱われる(変数名や関数名として使用出来る)。C++11から新たに追加された。 finalメンバ関数の宣言の直後、またはクラス宣言のクラス名の直後において文脈依存のキーワードとして扱われる。メンバ関数の宣言の直後では、その関数がオーバーライドされることを禁止する。クラス名の直後では、そのクラスから派生すること(基底クラスとして用いられること)を禁止する。 overrideメンバ関数の宣言の直後において文脈依存のキーワードとして扱われる。仮想関数が基底クラスのメンバ関数をオーバーライドすることを明示する。 代替表現代替字句(alternative token)のうちの、記号ではなくアルファベット(と下線)で表現する代替表現(alternative representation)は、キーワードには列挙されていないが、キーワードと同様に扱われる。ISO 14882の英語版の注ではlexical keywords(字句的にはキーワードであるもの)という表現が使われているが、JIS X 3014:2003の注では「予約語」という用語を用いて説明されている。 C/C++ではASCIIの記号類を多用しているので、ISO/IEC 646のUS以外を使用している環境では問題がある。それらの代用として、問題のない文字だけで表現するのが代替字句である(同じ用途のものとして他にトライグラフがある)。代替字句のうち、記号で表すダイグラフ(規格票の用語では「二つ組」)以外が代替表現である。これらはCではマクロ(ヘッダiso646.h、C95で標準化された)だが、C++では言語の一部である。 以下にそれぞれ対応する演算子を示してある。
C言語のキーワードのうち、C++ではキーワードでないものC99 のキーワードのうち _Bool, _Complex, _Imaginary, restrict は C++ のキーワードではない。C11 で追加になったキーワードのうち _Alignas, _Atomic, _Generic, _Noreturn, _Static_assert, _Thread_local は C++ のキーワードではない。C99 の _Bool には C++ の bool が対応する。また、_Complex に関しては、代わりに std::complex クラステンプレートが標準C++ライブラリに存在する。 C++20で予定されている変更C++の次期規格C++20では、機能の追加に伴い、新しいキーワードの追加、既存のキーワードへの意味の追加が予定されている。 追加のキーワード
(基本型)UTF-8の文字を格納するための整数型を表す。
(新機能:コンセプト)コンセプトを定義する。コンセプトは、型が満たすべき要件に名前を与える新しいプリミティブである。
(関数指定子)変数や関数を修飾して、コンパイル時定数となることを指示する。
(新機能:コンセプト)テンプレート引数のコンセプト要求を指定する定数式を指定する。 追加の文脈依存のキーワード
(アトリビュート) 脚注注釈
出典
参考文献
関連項目 |
Portal di Ensiklopedia Dunia