web-dev-qa-db-ja.com

C++識別子でアンダースコアを使用する際の規則は何ですか?

C++では、メンバー変数にローカル変数やパラメーターではなくメンバー変数であるという事実を示すために、メンバー変数に何らかのプレフィックスを付けることが一般的です。 MFCの経歴を持っている人は、おそらくm_fooを使うでしょう。私は時々myFooも見ました。

_fooのように、C#(あるいはおそらく.NET)はアンダースコアだけを使うことを推奨するようです。これはC++標準で許可されていますか?

871
Roger Lipscombe

規則(C++ 11では変更されていません)

  • implementation マクロとしての使用を含め、あらゆるスコープで予約済み:
    • アンダースコアで始まり、直後に大文字が続く識別子
    • 隣接するアンダースコア(または「ダブルアンダースコア」)を含む識別子
  • グローバル名前空間で予約されている:
    • 下線で始まる識別子
  • また、std名前空間内のすべてのものは予約されています。 (ただし、テンプレートの特殊化を追加することは許可されています。)

2003 C++標準から:

17.4.3.1.2グローバル名[lib.global.names]

名前と関数シグネチャの特定のセットは、常に実装用に予約されています。

  • 二重下線(__)を含む、または下線文字の後に大文字(2.11)が続く各名前は、使用のために実装に予約されています。
  • アンダースコアで始まる各名前は、グローバル名前空間の名前として使用するために実装に予約されています。165

165) そのような名前は名前空間::std(17.4.3.1)でも予約されています。

C++はC標準(1.1/2、C++ 03)に基づいており、C99は規範的な参照(1.2/1、C++ 03)であるため、1999 C標準からこれらも適用されます。

7.1.3予約済み識別子

各ヘッダーは、関連する副次句にリストされているすべての識別子を宣言または定義し、オプションで、関連する将来のライブラリの方向副次句にリストされている識別子およびファイルスコープ識別子として使用するために常に予約される識別子を宣言または定義します。

  • 下線と大文字または別の下線のいずれかで始まるすべての識別子は、常にあらゆる用途に予約されています。
  • アンダースコアで始まるすべての識別子は、通常のネームスペースとタグネームスペースの両方で、ファイルスコープを持つ識別子として使用するために常に予約されています。
  • 以下の副次句(将来のライブラリの指示を含む)のいずれかに含まれる各マクロ名は、関連するヘッダのいずれかが含まれている場合、指定どおりに使用するために予約されています。特に明記しない限り(7.1.4参照)。
  • (将来のライブラリの指示を含む)以下のいずれかの節にある外部リンケージを持つすべての識別子は、常に外部リンケージを持つ識別子として使用するために予約されています。154
  • 次の節(将来のライブラリの指示を含む)のいずれかに記載されているファイル有効範囲を持つ各識別子は、マクロ名として、および関連するヘッダーが含まれる場合は同じ名前空間のファイル有効範囲を持つ識別子として使用するために予約されています。

他の識別子は予約されていません。プログラムが予約されている文脈で識別子を宣言または定義している場合(7.1.4で許可されている場合を除く)、または予約済みの識別子をマクロ名として定義している場合の動作は未定義です。

プログラムが上記の最初のグループの識別子のマクロ定義を(#undefで)削除した場合の動作は未定義です。

154) 外部リンケージを持つ予約済み識別子のリストには、errnomath_errhandlingsetjmp、およびva_endがあります。

他の制限が適用される場合があります。たとえば、POSIX標準では、通常のコードで表示される可能性が高い多くの識別子を予約しています。

  • 大文字のEで始まる名前の後に数字または大文字が続く:
    • 追加のエラーコード名に使用できます。
  • isまたはtoのいずれかで始まり、その後に小文字が続く名前
    • 追加の文字テストおよび変換機能に使用できます。
  • LC_で始まり、その後に大文字が続く名前
    • ロケール属性を指定する追加のマクロに使用できます。
  • 接尾辞fまたはlが付いているすべての既存の数学関数の名前は予約されています
    • それぞれfloatおよびlong double引数を操作する対応する関数用です。
  • SIGで始まりその後に大文字が続く名前は予約されています
    • 追加の信号名については。
  • SIG_で始まりその後に大文字が続く名前は予約されています
    • 追加のシグナルアクション用。
  • strmem、またはwcsで始まり、その後に小文字が続く名前は予約されています
    • 追加の文字列および配列関数用。
  • PRIまたはSCNで始まり、その後に小文字またはXが続く名前は予約されています
    • 追加のフォーマット指定子マクロ
  • _tで終わる名前は予約されています
    • 追加の型名について.

これらの名前をあなた自身の目的のために今使用しても問題は起こらないかもしれませんが、それらはその規格の将来のバージョンと衝突する可能性を高めます。


個人的には、識別子をアンダースコアで始めることはしません。私のルールに新たに追加された機能:どこにも二重下線を使わないでください。下線はめったに使わないので簡単です。

この記事で調べた後、POSIX規格で予約されているので、識別子を_tで終わらせません。

_tで終わる識別子についての規則は私をとても驚かせました。私はそれが明確化と公式の章と詩を探しているPOSIX規格(まだわからない)であると思います。これは GNU libtoolマニュアル からのもので、予約されている名前をリストしています。

CesarBは、 POSIX 2004 の予約済みシンボルへの次のリンクを提供し、「他の多くの予約済みプレフィックスとサフィックス...がそこにあることを確認できる」と記しています。 POSIX 2008 予約シンボルはここで定義されています。制限は上記のものよりも多少微妙です。

794
Martin York

名前の衝突を避けるための規則は、C++標準(Stroustrupの本を参照)とC++の達人(Sutterなど)によって言及されています。

個人的なルール

私はケースを扱いたくなかったし、単純な規則を望んだので、私は単純で正しい両方の personal を設計しました。

シンボルを命名するときは、次のようにすれば、コンパイラ/ OS /標準ライブラリとの衝突を避けることができます。

  • アンダースコアでシンボルを始めないでください
  • 2つの連続したアンダースコアを内側に含むシンボルに名前を付けないでください。

もちろん、あなたのコードをユニークな名前空間に置くことは衝突を避けるのにも役立ちます(しかし邪悪なマクロから保護することはできません)

いくつかの例

(私はマクロを使用します。なぜなら、それらはC/C++シンボルのコード汚染が大きいからです。しかし、変数名からクラス名まで、何でも構いません)

#define _WRONG
#define __WRONG_AGAIN
#define RIGHT_
#define WRONG__WRONG
#define RIGHT_RIGHT
#define RIGHT_x_RIGHT

C++ 0xドラフトからの抽出

n3242.pdf ファイルから(私は最終的な標準テキストが似ていると思います):

17.6.3.3.2グローバル名[global.names]

名前と関数シグネチャの特定のセットは、常に実装用に予約されています。

- 二重下線_ _を含む、または下線文字で始まり大文字が続く各名前(2.12)は、使用のために実装に予約されています。

- アンダースコアで始まる各名前は、グローバル名前空間の名前として使用するために実装に予約されています。

だけでなく:

17.6.3.3.5ユーザー定義のリテラルサフィックス[usrlit.suffix]

アンダースコアで始まらないリテラル接尾辞識別子は、将来の標準化のために予約されています。

この最後の句は、1つのアンダースコアで始まり、その後に小文字が続く名前がOk ifであることを考慮しない限り、混乱を招きます。 ではない グローバル名前空間で定義されています...

185
paercebal

_ msdn _ :から

識別子の先頭に2つの連続したアンダースコア文字(__)を使用すること、または先頭に1つのアンダースコアとその後に大文字を使用することは、すべてのスコープでC++実装用に予約されています。現在または将来の予約済み識別子と競合する可能性があるため、ファイルの有効範囲を含む名前には、先頭に1つのアンダースコアを使用し、その後に小文字を使用することは避けてください。

これは、小文字が続く限り、メンバー変数のプレフィックスとして単一のアンダースコアを使用できることを意味します。

これは明らかにC++標準のセクション17.4.3.1.2から取られていますが、私は完全な標準オンラインのオリジナルのソースを見つけることができません。

この質問 も参照してください。

34
Roger Lipscombe

質問の他の部分に関しては、内部のものと衝突しないように、アンダースコアを変数名の end に置くのが一般的です。

(「グローバルスコープ内の名前の末尾、およびそれ以外の場所での名前の先頭」と比較して)1つの規則だけを覚えておけばよいので、クラスや名前空間の中でもこれを行います。

23
Max Lybbert

はい、アンダースコアは識別子のどこでも使用できます。最初の文字にa-z、A-Z、_のいずれか、続く文字に+ 0〜9のルールがあると私は考えています。

アンダースコアのプレフィックスはCコードでは一般的です。1つのアンダースコアは「プライベート」を意味し、2つのアンダースコアは通常コンパイラで使用するために予約されています。

3
John Millikin