34

ウィキペディアで私はこれを見つけました:

A a( A() );

[これ]は、次のいずれかとして明確にすることができます

  1. Aクラス[ ]の変数定義、クラス[ A]または
  1. Aタイプ[]のオブジェクトを返し、タイプ[ ]を返す(入力を受け取らない)関数である単一の(名前のない)引数を取る関数の関数宣言A

ほとんどのプログラマーは最初のものを期待していますが、C++標準では2番目のものとして解釈する必要があります。

しかし、なぜ?C ++コミュニティの大多数が前者の動作を期待している場合は、それを標準にしてみませんか?さらに、構文解析のあいまいさを考慮しない場合、上記の構文は一貫しています。

誰かが私を教えてくれませんか?なぜ規格はこれを要件にしているのですか?

4

6 に答える 6

20

MVPが存在しなかったとしましょう。

関数をどのように宣言しますか?

A foo();

メソッド宣言ではなく、変数定義になります。新しいキーワードを紹介していただけませんか?関数宣言の構文がもっと厄介ですか?またはあなたはむしろ持っていますか

A foo;

変数を定義し、

A foo();

関数を宣言しますか?

もう少し複雑な例は、この基本的な例との一貫性を保つためのものです。単一の変数定義でない限り、「宣言として解釈できるものはすべて宣言として解釈される」よりも、 「宣言として解釈できるものはすべて宣言として解釈される」と言う方が簡単です。それは変数定義です」

これはおそらくその背後にある動機ではありませんが、それが良いことである理由です。

于 2012-12-29T00:57:06.590 に答える
15

C ++の場合、これは非常に単純です。ルールはCでそのように作成されているためです。

Cでは、あいまいさはatypedefとかなりあいまいなコードでのみ発生します。偶然にそれをトリガーする人はほとんどいません。実際、可能性を示すために特別に設計されたコードを除いて、それはおそらくまれであると見なされます。しかし、良くも悪くも、あいまいさの単なる可能性は、誰かがそれを解決しなければならないことを意味しました-そして、記憶が役立つならば、それは宣言として解釈されることができるものはすべてであると宣言したデニス・リッチーによって解決されました定義としてあいまいな解釈もあったとしても、宣言。

C ++は、初期化に括弧を使用する機能と、グループ化としての関数呼び出しを追加しました。これにより、あいまいさがあいまいなものから一般的なものに変わりました。ただし、それを変更するには、Cからのルールを破る必要があります。この特定のあいまいさをほとんどの人が期待するように解決するために、さらに驚くべきことを5ダース以上作成せずに、あなたがいない限り、おそらくかなり重要でした。 Cとの互換性を完全に捨てることをいとわなかった。

于 2012-12-29T01:21:17.597 に答える
6

これは、文法が再帰的に定義されていることの副作用です。

そのように意図的に設計されたものではありません。それは最も厄介な解析として発見され、文書化されました。

于 2012-12-29T00:57:04.560 に答える
5

これは単なる推測ですが、特定のアプローチで両方の動作を取得できるという事実が原因である可能性があります。

A a( A() ); // this is a function declaration
A a( (A()) ); // this is a variable definition

その動作を変数定義に変更すると、関数宣言はかなり複雑になります。

typedef A subfunction_type();

A a( A() ); // this would be a variable declaration
A a( subfunction_type ); // this would be a function declaration??
于 2012-12-29T00:53:51.270 に答える
1

[おそらく]K-balloが特定した場合を除いて、特別な理由はありません。

それはただの遺産です。すでに構築フォームがあったので、ctorargsが機能していないときint x;に必要な範囲のようには見えませんでした。T x;

後から考えると、今日言語がゼロから設計されていれば、MVPは存在しないだろうと思います...他の多くのC++の奇妙な点もあります。

C ++は何十年にもわたって進化し、現在でも委員会によってのみ設計されていることを思い出してください(ラクダも参照)。

于 2012-12-29T00:53:36.933 に答える
1

プログラムがそのようなものであったかどうかを検討してください。

typedef struct A { int m; } A;
int main() { A a( A() ); }

これは有効なCであり、Cの文法で許可される解釈は1つだけaです。関数として宣言されています。Cは、=(括弧ではなく)を使用した初期化のみを許可A()し、式として解釈することはできません。(関数スタイルのキャストはC ++のみの機能です。)これは、Cの「vexingparse」ではありません。

ウィキペディアが指摘しているように、C++の文法はこの例を曖昧にします。ただし、C ++でこのプログラムにCと同じ意味を持たせたい場合は、明らかに、C++コンパイラはaCコンパイラと同じように関数として解釈する必要があります。確かに、C ++このプログラムの意味を変更してa、型の変数の定義を作成した可能性がありますA。ただし、Cとの非互換性は、正当な理由がある場合にのみC ++に導入されました。また、Stroustrupは、C ++に移行するCユーザーに大きなフラストレーションを与えるため、このような潜在的にサイレントな破損を特に避けたいと考えていました。

したがって、C ++はそれを変数定義ではなく、関数宣言としても解釈します。より一般的には、関数スタイルのキャストのように見えるものが、構文コンテキストではなく宣言として解釈できる場合は、そうなるという規則を採用しました。これにより、Cで利用できない解釈(つまり、関数スタイルのキャストを含む解釈)が行われないようにすることで、すべての厄介な状況でCとの非互換性の可能性が排除されます。

Cfront 2.0の選択された読み取り(1-42ページ)では、式宣言のあいまいさの場合のC互換性の問題について説明しています。これは、最も厄介な解析の関連タイプです。

于 2021-11-25T01:36:59.523 に答える