変数を宣言するときに、C ++で変数名を括弧で囲むことができるのはなぜですか?


84

たとえば、次のような宣言:

int (x) = 0;

またはそれでも:

int (((x))) = 0;

私のコードに次のようなフラグメントがあったため、これに遭遇しました。

struct B
{
};

struct C
{
  C (B *) {}
  void f () {};
};

int main()
{
  B *y;
  C (y);
}

明らかにC、デストラクタで役立つ何かを実行するオブジェクトを作成したかったのです。ただし、コンパイラは型C (y);を使用した変数の宣言として処理するため、再定義に関するエラーが出力されます。興味深いのは、私がそれをそのように、またはそのようなものとして書くと、意図したとおりにコンパイルされるということです。もちろん、最新の最善の回避策は、コンストラクター呼び出しで使用することです。yCyC (y).f ()C (static_cast<B*> (y)){}

そのため、後で理解したように、int (x) = 0;またはのような変数を宣言することは可能ですが、int (((x))) = 0;実際にこのような宣言を使用している人を見たことがありません。だから私は興味があります-今のところ、それは悪名高い「最も厄介な解析」に似たケースを作成するだけで、有用なものは何も追加しないので、そのような可能性の目的は何ですか?


可能性の「目的」は、おそらくパーサーを単純化することです。
molbdnilo 2015


1
@GSergリンクされた質問の2番目の回答からの質問に私の質問のテキストがどのように答えるかおかしいです。そのような宣言を許可すると予期しない結果が生じる例を提供するからです:)
Predelnik 2015


この罠に足を踏み入れた:ミューテックスがコメントアウトされたことを知らなかったため、誤って誤った括弧宣言を書き込んだ。// std :: mutex std :: unique_lock <std :: mutex>(m_mutex);
Laurijssenサーブ

回答:


80

グループ化。

特定の例として、次のような関数型の変数を宣言できることを考慮してください。

int f(int);

さて、あなたはそのようなものへのポインタをどのように宣言しますか?

int *f(int);

いいえ、機能しません!これは、を返す関数として解釈されますint*。正しい方法で解析するには、括弧を追加する必要があります。

int (*f)(int);

配列についても同じことが言えます。

int *x[5];   // array of five int*
int (*x)[5]; // pointer to array of five int

13
そして答えを完成させるために:質問者が尋ねている特定のケースを禁止することは特別なケースのルールを必要とするでしょう。()タイプでの動作の現在の定義は、タイプ全体で統一されています。
ジョセフマンスフィールド

したがって、特別な場合は、最も厄介な解析に適用されます。これは、コンストラクター引数を使用して変数を初期化するための構文が後で追加されたためです(急いでいると思いますか?)。
anArrayOfFunctions 2015

1
@FISOCPPまあ。。はい。C ++はCの後に来ました。。
iheanyi 2015

この答えは、C ++だけでなく、Cにも同様に当てはまりますか?
kdbanman 2015

関数型の変数」なに?!!
curiousguy 2015年

17

構文上の観点から、宣言は常に次のように見えるため、このような宣言では通常、括弧を使用できます。

<front type> <specification>;

たとえば、次の宣言では次のようになります。

int* p[2];

「フロントタイプ」はint(ではなくint*)であり、「仕様」は* p[2]です。

規則は、「仕様」の部分で必要に応じて任意の数の括弧を使用できるということです。括弧は明確にすることが避けられない場合があるためです。例えば:

int* p[2]; // array of 2 pointers to int; same as int (*p[2]);
int (*p)[2]; // pointer to an array of 2 ints

配列へのポインターはまれなケースですが、関数へのポインターの場合と同じ状況です。

int (*func(int)); // declares a function returning int*
int (*func)(int); // declares a pointer to function returning int

これはあなたの質問に対する直接の答えです。あなたの質問がのようなステートメントに関するものC(y)である場合、次のようになります。

  • 式全体を括弧で囲む(C(y))と、必要なものが得られます
  • このステートメントは、この命令が終了すると動作を停止する一時オブジェクトを作成するだけです(これがあなたの意図したことであることを願っています)。

1
先に述べたように、最初はデストラクタで何かを実行していましたが、パラメータを設定してデストラクタですべてのジョブを実行するための「チェーン」関数がいくつかある場合は、かなり標準的なことだと思います。回避策をもう1つありがとうございますが、{}結局のところ、書くことが最も有効なものだと思います。
Predelnik 2015

4
独自の文法を作成することは避け、標準で提供されているものを使用してください。<front-type> <specification>誤解を招く、そして間違っています。文法は<declaration-specifier> <declarator>
スティーブコックス

あなたは正しいです-私は標準を調べませんでした、ただ私の頭から規則を繰り返しました。実際、C ++ 11では、の役割はキーワードで<declaration-specifier>も果たすことができるautoため、必ずしも型であるとは限りません。
ethouris 2015

@Pravasi Meet:私の投稿の一部を編集し、指定された構文スキーマの名前を変更した場合は、それに応じて3行下の名前も変更してください。それ以外の場合は、「フロントタイプ」と「仕様」という古い名前がまだ存在するため、投稿は意味をなしません。
ethouris 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.