web-dev-qa-db-ja.com

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

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

_int (x) = 0;
_

それとも:

_int (((x))) = 0;
_

私のコードでは、たまたま次のようなフラグメントがあるため、私はこれにつまずきました。

_struct B
{
};

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

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

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

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

81
Predelnik

グルーピング。

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

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

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

_<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))_
  • このステートメントは、この命令が終了すると一時的なオブジェクトを作成すること以外は何もしません(これがあなたの意図したことです)。
17
Ethouris