web-dev-qa-db-ja.com

前の定数または後の定数?

開始するには、おそらくconstを使用して、オブジェクトのデータまたはポインターを変更不可、またはその両方にすることができることを知っているでしょう。

const Object* obj; // can't change data
Object* const obj; // can't change pointer
const Object* const obj; // can't change data or pointer

ただし、次の構文も使用できます。

Object const *obj; // same as const Object* obj;

重要であると思われる唯一のものは、アスタリスクのどちら側にconstキーワードを配置するかです。個人的には、タイプの左側にconstを配置して、データが変更可能でないことを指定することを好みます。

さらに重要なのは、なぜconstデータを指定する2つの正しい方法があり、どのような状況でどちらかを優先するか、必要とする場合がありますか?

編集:

私が生まれるずっと前に、コンパイラが物事をどのように解釈するかの標準が起草されたとき、これはarbitrary意的な決定であったように思えます。 constはキーワードの左側に適用されるので(デフォルトでは?)、キーワードと型修飾子を適用するために"shortcuts"を追加しても害はないと考えたと思います。少なくとも*または&...を解析して宣言が変更されるまでは、他の方法.

これは、Cでも同様でした。

123
AJG85

なぜconstデータを指定する正しい方法が2つあるのか、もしあれば、どのような状況でどちらを好むか、または必要とするのか。

基本的に、アスタリスクの前の指定子内のconstの位置が重要ではない理由は、C文法がKernighanとRitchieによってそのように定義されたためです。

彼らがこの方法で文法を定義した理由は、Cコンパイラが左から右への入力を解析し、それが消費されるたびに各トークンの処理を完了したためである可能性があります。 _*_トークンを使用すると、現在の宣言の状態がポインター型に変更されます。 _*_の後にconstに遭遇すると、const修飾子がポインター宣言に適用されます。 _*_の前にある場合、ポイントされたデータに修飾子が適用されます。

const修飾子が型指定子の前後にある場合、セマンティックの意味は変わらないため、どちらの方法でも受け入れられます。

関数ポインタを宣言するときに、同様のケースが発生します。ここで、

  • void * function1(void)は_void *_を返す関数を宣言します。

  • void (* function2)(void)は、voidを返す関数に対してfunction pointerを宣言します。

再び注意すべきことは、言語構文が左から右へのパーサーをサポートしていることです。

79
Heath Hunnicutt

ルールは次のとおりです。

constは、残りのものに適用されます。左側に何もない場合は、右側に適用されます。

Constが定義される「オリジナル」の方法であるという理由だけで、constの右側でconstを使用することを好みます。

しかし、これは非常に主観的な視点だと思います。

63
horstforst

2番目の構文を好みます。型宣言を右から左に読むことで、「何」が一定であるかを追跡するのに役立ちます。

Object * const obj;        // read right-to-left:  const pointer to Object
Object const * obj;        // read right-to-left:  pointer to const Object
Object const * const obj;  // read right-to-left:  const pointer to const Object
46
Matt Davis

宣言内のキーワードの順序はそれほど固定されていません。 「1つの真の順序」には多くの選択肢があります。このような

int long const long unsigned volatile i = 0;

またはそれがあるべき

volatile unsigned long long int const i = 0;

33
Bo Persson

最初のルールは、ローカルコーディング標準で必要な形式を使用することです。その後:constを前に置くと、typedefが関係するときに混乱が終わりません。例えば:

typedef int* IntPtr;
const IntPtr p1;   // same as int* const p1;

コーディング標準でポインタのtypedefが許可されている場合、実際にはconstをtypeの後に配置する必要があります。型に適用される場合を除き、constは適用対象に従う必要があるため、一貫性は後にconstを支持することも主張します。しかし、ローカルコーディングガイドラインはこれらすべてより優先されます。通常、その差は戻って既存のすべてのコードを変更するほど重要ではありません。

6
James Kanze

左右どちらでもよいという歴史的な理由があります。 Stroustrupは1983年までにC++にconstを追加していました ですが、C89/C90までCになりませんでした。

C++では、常にconstを右側に使用する正当な理由があります。 constメンバー関数mustは次のように宣言されるため、どこでも一貫性が保たれます。

int getInt() const;
5
Nick Westgate