Namespaces
Variants

Declarations

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
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

宣言 は、名前をC++プログラムに導入(または再導入)する方法です。すべての宣言が実際に何かを宣言するわけではなく、各種エンティティはそれぞれ異なる方法で宣言されます。 定義 は、名前で識別されるエンティティを使用するのに十分な宣言です。

宣言は以下のいずれかです:

(C++11以降)
  • 空の宣言 ( ; )
  • decl-specifier-seq を持たない関数宣言:
attr  (任意) declarator ;
attr - (since C++11) 任意の数の 属性 のシーケンス
declarator - 関数宣言子
この宣言はコンストラクタ、デストラクタ、またはユーザー定義型の conversion function を宣言しなければなりません。これは template declaration explicit specialization または明示的インスタンス化の一部としてのみ使用できます。
  • block-declaration (ブロック内に現れることができる宣言( ブロック を参照))。これは以下のいずれかになります:
(C++11以降)
(C++20以降)
(C++11以降)
  • 単純宣言

目次

翻訳のポイント: - 「Contents」→「目次」に翻訳 - C++専門用語(Simple declaration, Specifiers, Declarators, Notes, Example, Defect reports, See also)は原文のまま保持 - HTMLタグ、属性、クラス名、IDは一切変更せず - 数値、リンク、構造は完全に保持

単純宣言

単純宣言は、1つまたは複数の識別子(通常は変数)を導入し、作成し、必要に応じて初期化する文です。

decl-specifier-seq init-declarator-list  (省略可能) ; (1)
attr decl-specifier-seq init-declarator-list ; (2) (C++11以降)
decl-specifier-seq - 一連の 指定子
init-declarator-list - init-declarator のカンマ区切りリスト(下記参照)
attr - 任意の数の 属性 のシーケンス


init-declarator-list は、名前付きクラスまたは名前付き列挙型を宣言する場合にのみ省略できます。

構造化束縛宣言 も単純宣言である。

(C++17以降)


init-declarator の構文は以下のように定義されます:

declarator initializer (1)
declarator requires-clause  (オプション) contract-specs  (オプション) (2)
1) 初期化子を持つ宣言子。
2) 初期化子なしの宣言子。
declarator - a declarator
initializer - an initializer
requires-clause - (since C++20) a requires clause
contract-specs - (since C++26) a list of function contract specifiers


requires-clause は、 declarator テンプレート化された関数 を宣言する場合にのみ現れます。

(C++20以降)

contract-specs は、 declarator が関数または関数テンプレートを宣言する場合にのみ現れます。

(C++26以降)

指定子

宣言指定子 ( decl-specifier-seq ) は、任意の順序で以下の空白区切りの指定子の列です:

  • inline 指定子は変数宣言でも使用可能です。
(C++17以降)
  • the friend 指定子、クラスおよび関数宣言で許可されます。
  • constexpr 指定子は、変数定義、関数および関数テンプレートの宣言、リテラル型の静的データメンバーの宣言でのみ使用可能。
(C++11以降)
  • consteval 指定子は、関数および関数テンプレートの宣言でのみ使用可能。
  • constinit 指定子は、静的またはスレッド記憶域期間を持つ変数の宣言でのみ使用可能。 constexpr consteval constinit 指定子のうち、最大1つだけが decl-specifier-seq に現れることが可能。
(C++20以降)
  • ストレージクラス指定子 ( register , (C++17まで) static , thread_local , (C++11から) extern , mutable )。ストレージクラス指定子は1つだけ許可される 、ただし thread_local extern または static と一緒に使用できる (C++11から)
  • 型指定子 ( type-specifier-seq )、型を指定する一連の指定子。宣言によって導入されるすべてのエンティティの型は、この型(必要に応じて宣言子によって修飾される)となる。この一連の指定子は type-id でも使用される。 type-specifier-seq の一部となる指定子は以下のみ(任意の順序で):
(C++11以降)
(C++26以降)
  • 以前に宣言されたクラス名(オプションで 修飾 可能)
  • 以前に宣言されたenum名(オプションで 修飾 可能)
  • 以前に宣言された typedef-name または type alias (C++11以降) (オプションで 修飾 可能)
  • テンプレート引数を伴うテンプレート名(オプションで 修飾 可能、オプションで template disambiguator を使用可能)
(C++17以降)
  • キーワード class struct または union に続けて、クラス名として以前に定義された識別子(任意で 修飾 可能)。
  • キーワード class struct または union に続けて、クラステンプレート名として以前に定義されたテンプレート引数付きのテンプレート名(任意で 修飾 可能、任意で template 曖昧性除去子 を使用可能)。
  • キーワード enum に続けて、列挙型名として以前に宣言された識別子(任意で 修飾 可能)。
decl-specifier-seqでは、以下の例外を除いて型指定子は1つだけ許可されます:
  • const は自身を除く任意の型指定子と組み合わせ可能。
  • volatile は自身を除く任意の型指定子と組み合わせ可能。
  • signed または unsigned char long short 、または int と組み合わせ可能。
  • short または long int と組み合わせ可能。
  • long double と組み合わせ可能。
  • long long と組み合わせることができます。
(C++11以降)

Attributes decl-specifier-seq 内に現れることがあり、その場合、それらは先行する指定子によって決定される型に適用されます。

宣言指定子シーケンス内での任意の指定子の繰り返し、例えば decl-specifier-seq 内の const static const virtual inline virtual はエラーとなります 、ただし long が2回出現することは許可されます (C++11以降)

宣言子

init-declarator-list 内の各 init-declarator は、同じ指定子を持つ独立した宣言であるかのように処理されます: S D1, D2, D3 ; S D1 ; S D2 ; S D3 ; として扱われます。

各宣言子は、正確に1つのオブジェクト、参照、関数、または(typedef宣言の場合)型エイリアスを導入します。その型は decl-specifier-seq によって提供され、宣言子内の & (参照)や [ ] (配列)や ( ) (関数返却)などの演算子によって任意に修飾されます。これらの演算子は、以下に示すように再帰的に適用できます。

A declarator は以下のいずれかです:

unqualified-id attr  (任意) (1)
qualified-id attr  (任意) (2)
... identifier attr  (任意) (3) (C++11以降)
* attr  (任意) cv  (任意) declarator (4)
nested-name-specifier * attr  (任意) cv  (任意) declarator (5)
& attr  (任意) declarator (6)
&& attr  (任意) declarator (7) (C++11以降)
noptr-declarator [ constant-expression  (任意) ] attr  (任意) (8)
noptr-declarator ( parameter-list ) cv  (任意) ref   (任意) except  (任意) attr  (任意) (9)
( declarator ) (10)
1) 宣言された name
2) 修飾識別子( qualified identifier qualified-id ))を使用する宣言子は、以前に宣言された namespace member または class member を定義または再宣言します。
3) Parameter pack , パラメータ宣言 でのみ現れる。
4) ポインタ宣言子 : 宣言 S * D ; D decl-specifier-seq S によって決定される型へのポインタとして宣言する。
5) メンバへのポインタ宣言 : 宣言 S C :: * D ; D C のメンバへのポインタとして宣言し、その型は decl-specifier-seq S によって決定される。 nested-name-specifier 名前とスコープ解決演算子のシーケンス ::
6) 左辺値参照宣言子 : 宣言 S & D ; D decl-specifier-seq S によって決定される型への左辺値参照として宣言する。
7) 右辺値参照宣言子 : 宣言 S && D ; D decl-specifier-seq S によって決定される型への右辺値参照として宣言する。
8) 配列宣言子 . noptr-declarator 任意の有効な宣言子ですが、*、&、または&&で始まる場合は括弧で囲む必要があります。
9) 関数宣言子 . noptr-declarator 任意の有効な宣言子。ただし、*、&、または&&で始まる場合は括弧で囲む必要があります。 オプションの末尾戻り値型で終了しても構いません。 (C++11以降)
10) 括弧で囲まれた宣言子。

すべての場合において、 attr はオプションの 属性 シーケンスです。識別子の直後に現れる場合、宣言されるオブジェクトに適用されます。

(C++11以降)

cv const および volatile 修飾子のシーケンスであり、各修飾子はシーケンス内に最大1回のみ出現することができます。

注記

ブロック内で block-declaration が現れた場合、かつ宣言によって導入された識別子が以前に外側のブロックで宣言されていたとき、 外側の宣言は隠蔽されます (そのブロックの残りの部分に対して)。

自動記憶域期間を持つ変数を宣言する場合、その宣言文が実行されるときに初期化されます。ブロック内で宣言されたすべての自動変数は、ブロックから退出する際に(例外、goto、またはブロック終端への到達など、どのようにブロックを退出したかに関係なく)破棄され、初期化の順序と逆の順序で破棄されます。

注: この例は、複雑な宣言が言語文法の観点からどのように解析されるかを示しています。他の一般的な記憶法としては: スパイラルルール 内側から外側への読み方 、および 宣言が使用法を反映する があります。また自動解析ツールが https://cdecl.org で利用可能です。

#include <type_traits>
struct S
{
    int member;
    // decl-specifier-seq is "int"
    // declarator is "member"
} obj, *pObj(&obj);
// decl-specifier-seq is "struct S { int member; }"
// declarator "obj" declares an object of type S
// declarator "*pObj" declares a pointer to S,
//     and initializer "(&obj)" initializes it
int i = 1, *p = nullptr, f(), (*pf)(double);
// decl-specifier-seq is "int"
// declarator "i" declares a variable of type int,
//     and initializer "= 1" initializes it
// declarator "*p" declares a variable of type int*,
//     and initializer "= nullptr" initializes it
// declarator "f()" declares (but doesn't define)
//     a function taking no arguments and returning int
// declarator "(*pf)(double)" declares a pointer to function
//     taking double and returning int
int (*(*var1)(double))[3] = nullptr;
// decl-specifier-seq is "int"
// declarator is "(*(*var1)(double))[3]"
// initializer is "= nullptr"
// 1. declarator "(*(*var1)(double))[3]" is an array declarator:
//    Type declared is: "(*(*var1)(double))" array of 3 elements
// 2. declarator "(*(*var1)(double))" is a pointer declarator:
//    Type declared is: "(*var1)(double)" pointer to array of 3 elements
// 3. declarator "(*var1)(double)" is a function declarator:
//    Type declared is: "(*var1)" function taking "(double)",
//    returning pointer to array of 3 elements.
// 4. declarator "(*var1)" is a pointer declarator:
//    Type declared is: "var1" pointer to function taking "(double)",
//    returning pointer to array of 3 elements.
// 5. declarator "var1" is an identifier.
// This declaration declares the object var1 of type "pointer to function
// taking double and returning pointer to array of 3 elements of type int"
// The initializer "= nullptr" provides the initial value of this pointer.
// C++11 alternative syntax:
auto (*var2)(double) -> int (*)[3] = nullptr;
// decl-specifier-seq is "auto"
// declarator is "(*var2)(double) -> int (*)[3]"
// initializer is "= nullptr"
// 1. declarator "(*var2)(double) -> int (*)[3]" is a function declarator:
//    Type declared is: "(*var2)" function taking "(double)", returning "int (*)[3]"
// ...
int main()
{
    static_assert(std::is_same_v<decltype(var1), decltype(var2)>);
}

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用バージョン 公開時の動作 正しい動作
CWG 482 C++98 再宣言の宣言子は修飾できなかった 修飾された宣言子が許可される
CWG 569 C++98 単独のセミコロンは有効な宣言ではなかった 空宣言となり、
効果を持たない
CWG 1830 C++98 decl-specifier-seq 内での関数指定子の繰り返しが許可されていた 繰り返しは禁止される

関連項目