C / C ++プログラミング:属性(attr)、指定子

属性

効果

  • タイプ、オブジェクト、コードなどの実装定義の属性を導入します。
  • 属性は、さまざまな実装定義の言語拡張(GNUおよびIBMの言語拡張属性((...))、Microsoftの言語拡張__declspec()など)の統一された構文提供します。
  • 属性は、C ++プログラムのほぼすべての場所で使用でき、タイプ、変数、関数、名前、コードブロック、変換単位全体など、ほぼすべてに適用できますが、特定の各属性は、実装で許可されている場合にのみ有効です。
    • [[expect_true]]は、クラス宣言ではなく、ifでのみ使用できる属性である可能性があります
    • [[omp :: parallel()]]は、int型の属性ではなく、コードブロックまたはforループに適用できます。
  • 公式文書

文法

[[attr]] [[attr1, attr2, attr3(args)]] [[namespace::attr(args)]] alignas-说明符 (1)
[[ 属性列表 ]] (2)
[[ using 属性命名空间 : 属性列表 ]] (3)

(1)例

[[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]]
inline int f1(); // 声明 f 带四个属性

(2)例

[[gnu::always_inline, gnu::const, gnu::hot, nodiscard]]
int f2(); // 同上,但使用含有四个属性的单个属性说明符

(3)例:

[[using gnu : const, always_inline, hot]] [[nodiscard]]
int f[[gnu::always_inline]](); // 属性可出现于多个说明符中

指定子

指定子には次のものがあります。

  • typedef指定子。存在する場合、宣言全体がtypedef宣言であり、各宣言子はオブジェクトや関数ではなく、新しい型名を導入します。
  • 関数指定子(インライン、仮想、明示的)は、関数宣言でのみ許可されます。C ++ 17以降、変数宣言インラインを使用することもできます
  • フレンド指定子は、クラスおよび関数の宣言で許可されます
  • C ++ 11以降、constexpr指定子は、変数定義、関数と関数テンプレートの宣言、およびリテラル型の静的データメンバーの宣言でのみ使用できます。
  • C ++ 20以降、consteval指定子は関数および関数テンプレート宣言でのみ使用できます。
  • C ++ 20以降、constinit指定子は、静的またはスレッドの保存期間を持つ変数宣言でのみ使用できます。ステートメントのシーケンスディスクリプタ最も許さconstexprので、consteval constinitと1つの指定子。
  • ストレージクラス指定子(register、static、thread_local(C ++ 11以降)、extern、mutable)。1つのストレージクラス指定子のみが許可されますが、thread_localはexternまたはstaticで表示できます。
  • 型指定子(型指定子シーケンスとも呼ばれます)。型指定子は、スペースで区切られた一連の指定子です(次の指定子のみを含めることができます)
    • クラス指定子:class、struct、union
    • 列挙型指定子:列挙型
    • 単純型指定子
      • char、char8_t(C ++ 20起)、char16_t、char32_t(C ++ 11起)、wchar_t、bool、short、int、long、signed、unsigned、float、double、void
      • 自動、decltype指定子
      • 以前に宣言されたクラス名、列挙名、typedef名、(C ++ 11以降)タイプエイリアス
      • テンプレート引数付きのテンプレート名、テンプレート引数なしのテンプレート名
    • 詳細な型指定子
      • キーワードclass、struct、またはunionの後に、以前にclass、struct、またはunion名として定義された識別子が続く
      • キーワードclass、struct、またはunion、テンプレート名、テンプレート引数が続きます。これは、クラステンプレートの名前として以前に定義されています。
      • キーワードenumの後には、以前に列挙名として定義された識別子が続きます
    • タイプ名指定子
    • cv修飾子指定子

宣言指定子シーケンス

  • 宣言指定子のシーケンス(宣言指定子と呼ばれる)は、任意の順序でブランク区切られた指定子のシーケンスです。
  • 次の例外を除いて、宣言指定子シーケンス許可される型指定子は1つだけです。
    • const 、volatile それ自体の外部の任意のタイプ指定子と組み合わせることができます
    • signedまたは、unsignedcanとchar、long、short int、またはそれらの組み合わせ。
    • shortまたはlongintと組み合わせることができます
    • longロングと組み合わせることができます。(C ++ 11以降)
      • 宣言指定子シーケンスで2回出現することを許可する唯一の指定子は長いです(2回出現する可能性があります)。const static constやvirtualinline virtualなど、他のすべての繰り返しはエラーです(C ++ 17以降)。
  • 属性宣言指定子に表示できます。その場合属性その前に指定子によって決定された型に適用されます。

宣言者

宣言指定子シーケンスと宣言子は2つの異なるものです。例を参照してください

class C {
    
    
    std::string member; // 声明说明符序列 为 "std::string"
                        // 声明符 为 "member"
} obj, *pObj(&obj);
// 声明说明符序列 为 "class C { std::string member; }"
// 声明符 "obj" 定义 C 类型的对象
// 声明符 "*pObj(&obj)" 声明并初始化指向 C 的指针
 
int a = 1, *p = nullptr, f(), (*pf)(double);
// 声明说明符序列 为 int
// 声明符 a=1 定义并初始化 int 类型的变量
// 声明符 *p=NULL 定义并初始化 int* 类型的变量
// 声明符 (f)() 声明(但不定义)不接收参数并返回 int 的函数
// 声明符 (*pf)(double) 定义指向接收 double 并返回 int 的函数的指针
 
int (*(*foo)(double))[3] = nullptr;
// decl-specifier-seq 为 int
// 1. 声明符 "(*(*foo)(double))[3]" 是数组声明符;
//    所声明类型是“int 的 3 元素数组 /嵌套声明符/ ”
// 2. 嵌套声明符是 "(*(*foo)(double))",它是指针声明符
//    所声明类型是“int 的 3 元素数组 的指针 /嵌套声明符/”
// 3. 嵌套声明符是 "(*foo)(double)",它是函数声明符
//    所声明类型是“以 int 的 3 元素数组 的指针 为返回值的接受一个 double 参数的函数 /嵌套声明符/”
// 4. 嵌套声明符是 "(*foo)",它是(带括号,如函数声明符语法所要求的)指针声明符。
//    所声明类型是“以 int 的 3 元素数组 的指针 为返回值的接受一个 double 参数的函数 的指针 /嵌套声明符/”
// 5. 嵌套声明符是 "foo",它是标识符。
// 该声明声明了对象 foo,其类型为“以 int 的 3 元素数组 的指针 为返回值的接受一个 double 参数的函数 的指针”
// 初始化器 "= nullptr" 提供此指针的初值。

その他

修飾されていない識別式の前にあるスコープ解決演算子は制限されています::

おすすめ

転載: blog.csdn.net/zhizhengguan/article/details/114985589