我不明白为啥会这样编译

Posted

技术标签:

【中文标题】我不明白为啥会这样编译【英文标题】:I do not understand why this compiles我不明白为什么会这样编译 【发布时间】:2020-03-28 11:07:27 【问题描述】:

我当然遗漏了一些东西,但我不明白为什么会编译(同时使用 g++ 和 clang++):

struct A

;
struct B

;

int main()

  A a(B);

首先,B 是一个类型...不是一个值。我应该如何解释这段代码?

【问题讨论】:

这被称为Most Vexing Parse @alterigel 真的吗?在这种情况下,没有歧义。它只能是一个函数声明。不是A a(B());,它可以是变量定义或函数声明。 你会惊讶地发现struct A; int main() A(foo); compiles as is,即使foo 没有说出任何名字。 @alterigel -- 这不是最令人头疼的解析。查看您链接到的页面上的示例。这只是一个函数声明。 @PeteBecker,最好解释一下为什么这不是 MVP,而不是仅仅断言它不是,我相信 walnut 已经在上面做了。 【参考方案1】:

它被解释为一个名为a 的函数的声明,它接受一个B 类型的参数并返回A

【讨论】:

这就是为什么它是 Most 和 Vexing。一个解决方案:(并不是说它实际上解决了任何问题,因为它暴露了糟糕的结构)A aB; @user4581301 -- 它不是最令人头疼的解析。它只是一个函数声明。 最奇怪的是C++不允许嵌套函数,但确实允许在函数内声明。 听起来像是向 C++ 添加对嵌套函数的支持的好动机;它们不仅有用,而且会将这种奇怪的疣变成合理的设计:) @Brian “有点违反直觉”可能是 C++ 的座右铭 :)。至于前向声明,我认为它们不支持本地函数,并称之为完成。【参考方案2】:

这只是一个函数声明,将a 声明为一个返回A 并采用B 类型的未命名参数的函数。

这是有效的,因为在函数定义中允许函数声明而不是函数定义。

【讨论】:

【参考方案3】:

这个问题被称为most vexing parseA a(B); 行可以解释为一个名为 a 的函数的声明,它返回一个 A 类型的对象并采用 B 类型的未命名参数。

避免此问题的一种方法是使用在 C++11 中引入的 统一初始化 语法,该语法包括使用大括号而不是括号:A aB; 返回错误。该行现在被解释为使用B 初始化的变量声明,这是一个类型而不是一个值。

这里有更多信息:

The Most Vexing Parse: How to Spot It and Fix It Quickly

【讨论】:

我认为这不应该被称为“最令人头疼的解析”。它只是一个通常的函数声明,因为它也存在于 C 中。没有必要的歧义解决,因为该行只能是一个函数声明,没有别的。看看你的链接。示例都与此不同。 虽然确实如此,但它与最令人头疼的解析有关。只是这还包括一个错字,其中单独使用类型名称而不是变量或构造函数调用,这可能是最初的意图。 是的,“Most Vexing Parse”在这种情况下是一个有用的答案,即使问题中的实际情况只是“Slightly Vexing Parse”。 @wlanut:空结构struct A ; 在标准 C 中无效,即使某些编译器允许它们。放下牙套,那里就不会有问题了。此外,在 C 中,声明或定义 struct A 不会创建类型名称 A(您必须为其添加前缀 struct,或者在使用 A 之前的某处添加 typedef struct A A; 而不使用 struct 前缀)。同样在 C 语言中,函数声明没有替代解析——使用 type name(...); 根本不可能是变量定义;它始终是函数声明(或无效)。问题中的代码在 C 中无效。 @jpa,我在任何地方都找不到任何关于“Slightly Vexing Parse”的文章。这个名字只是口头传统吗?我想了解更多。

以上是关于我不明白为啥会这样编译的主要内容,如果未能解决你的问题,请参考以下文章

编译错误:Next without For || VBA

编译代码后它崩溃(不明白为啥)

为啥我们在编译组合 GAN (SRGAN) 网络时使用两个损失

一直报错,不明白为啥

我用myeclipse开发web程序,其中myeclipse有一个重新编译的功能,我不明白怎么重新编译,

为啥声明“2i;”不会导致编译器错误?