34

维基百科上我发现了这个:

A a( A() );

[This] 可以消除歧义

  1. 类 [ ]的变量定义,采用类 [ A] 的匿名实例A
  1. 一个函数的函数声明,它返回一个 [ A] 类型的对象并接受一个(未命名的)参数,该参数是一个返回类型 [ A] 的函数(并且不接受输入)。

大多数程序员期望第一个,但 C++ 标准要求将其解释为第二个。

但为什么?如果 C++ 社区的大多数人都期望前一种行为,为什么不将其作为标准呢?此外,如果考虑解析歧义,上述语法是一致的。

有人可以启发我吗?为什么该标准将其作为一项要求?

4

6 回答 6

20

假设 MVP 不存在。

你将如何声明一个函数?

A foo();

将是一个变量定义,而不是一个方法声明。你会介绍一个新的关键字吗?函数声明的语法会更尴尬吗?或者你宁愿有

A foo;

定义一个变量和

A foo();

声明一个函数?

您稍微复杂的示例只是为了与这个基本示例保持一致。说“所有可以解释为声明的东西都将被解释为声明”而不是“所有可以解释为声明的东西都将被解释为声明”更容易,除非它是单个变量定义,在这种情况下这是一个变量定义”

虽然这可能不是它背后的动机,但它是一件好事

于 2012-12-29T00:57:06.590 回答
15

对于 C++,这非常简单:因为规则是在 C 中以这种方式制定的。

在 C 语言中,歧义只出现在 atypedef和一些相当晦涩的代码中。几乎没有人会意外触发它——事实上,除了专门为展示这种可能性而设计的代码之外,它可能是罕见的。然而,无论好坏,这种模棱两可的可能性意味着必须有人解决它——如果没记错的话,正是丹尼斯·里奇(Dennis Ritchie)解决了这个问题,丹尼斯·里奇(Dennis Ritchie)下令任何可以被解释为声明的东西都是声明,即使作为定义也存在模棱两可的解释。

C++ 增加了使用括号进行初始化以及函数调用作为分组的能力,这将模糊性从模糊变为常见。然而,改变它需要打破来自 C 的规则。像大多数人所期望的那样解决这个特殊的歧义,而不创造更多更令人惊讶的六个可能也相当不简单,除非你愿意完全放弃与 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 确定的情况。

这只是遗产。已经有了构造形式,所以当没有 ctor args 起作用时int x;,它似乎从来都不是需要的。T x;

事后看来,我想如果该语言是从头开始设计的,那么 MVP 将不存在......以及大量其他 C++ 怪事。

回想一下,C++已经发展了几十年,即使是现在,也只是由委员会设计的(另请参见:camel)。

于 2012-12-29T00:53:36.933 回答
1

考虑一下程序是否是这样的:

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

这将是有效的 C,并且 C 的语法只允许一种可能的解释:a被声明为函数。C 只允许使用(而不是括号)进行初始化=,并且不允许A()被解释为表达式。(函数样式转换是 C++ 独有的特性。)这不是 C 中的“令人烦恼的解析”。

正如 Wikipedia 指出的那样,C++ 的语法使这个例子变得模棱两可。但是,如果您希望 C++ 赋予该程序与 C 相同的含义,那么显然,C++ 编译器将不得不a像 C 编译器一样将其解释为函数。当然,C++可以改变这个程序的含义,a定义一个类型为 的变量A。然而,只有在有充分理由时才将与 C 的不兼容性引入 C++,我想 Stroustrup 特别希望避免此类潜在的无声破坏,因为它们会给迁移到 C++ 的 C 用户带来极大的挫败感。

因此,C++ 也将其解释为函数声明,而不是变量定义;更一般地说,采用的规则是,如果看起来像函数样式转换的东西可以在其句法上下文中被解释为声明,那么它应该是。通过确保不采用 C 中不可用的解释(涉及函数样式转换的解释),这消除了在所有令人烦恼的解析情况下与 C 不兼容的可能性。

Cfront 2.0 Selected Readings(第 1-42 页)在表达式声明歧义的情况下提到了 C 兼容性问题,这是最令人头疼的解析的相关类型。

于 2021-11-25T01:36:59.523 回答