最令人烦恼的解析是一个正式定义的概念吗

use*_*570 19 c++ most-vexing-parse language-lawyer

我正在阅读一篇 SO 帖子,其中一位用户发表了以下评论

另请注意,ArrTest<int> ar();使用了最令人烦恼的 parse

但另一位用户却表示相反:

ArrTest<int> ar();不是“最令人烦恼的解析”。这只是一个函数声明。对于初学者来说这当然很麻烦,但是,正如您链接到的页面所示,“最令人烦恼的解析”更加复杂。

下面给出了该帖子中的代码示例以供参考:

template <class ItemType>
class ArrTest {
public:
    ArrTest();
private:
    ItemType* info;
};
//some other code here

int main() {
    ArrTest<int> ar();  //DOES THIS USE THE MOST VEXING PARSE?
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的第一个问题是 C++ 标准正式定义的“最令人烦恼的解析”的概念。我的第二个问题是该语句是否ArrTest<int> ar();使用了最令人烦恼的解析。也就是说,上面引用的两条评论哪一条在技术上是正确的?


似乎也表明这MyObject object();是最令人烦恼的解析。

eer*_*ika 17

是 C++ 标准正式定义的“最令人烦恼的解析”的概念。

不。C++ 标准中没有定义“最令人烦恼的解析”的概念。该标准确实定义了产生歧义的语法,并且定义了解决歧义的规则,但它没有命名歧义。

根据 Wikipedia 的说法:“‘最令人烦恼的解析’这个术语最初是由 Scott Meyers 在他 2001 年出版的《Effective STL》一书中使用的。” 。书中的例子是:

第 6 项:警惕 C++ 最令人烦恼的解析。

ifstream dataFile("ints.dat");
list<int> data(istream_iterator<int>(dataFile), // warning! this doesn't do
               istream_iterator<int>());        // what you think it does
Run Code Online (Sandbox Code Playgroud)

我描述“MVP”的方式是,意图声明一个带有传递参数的变量,但最终您实际上编写了一个函数声明,并且预期的参数最终成为参数声明符。


ArrTest ar(); 语句执行吗?使用最令人烦恼的解析。

书中也明确提到了这种歧义:

如果您已经使用 C++ 编程了一段时间,那么您几乎肯定遇到过该规则的另一种表现形式。这种错误你见过多少次了?

class Widget {...}; // assume Widget has a default constructor
Widget w();         //'uh oh...
Run Code Online (Sandbox Code Playgroud)

鉴于提出歧义名称的作者认为这是语言规则的另一种表现形式(而不是同一种表现形式),我想说,所讨论的示例不是“MVP”。这是另一个类似的,在我看来不那么令人烦恼的歧义。

  • 作者写道:*“你几乎肯定遇到过这个规则的另一种表现形式。”*然后给出了 `Widget w();` 的例子。既然作者自己说这个例子就是这个(最令人烦恼的解析)规则的体现,那么这里有什么问题呢。我的意思是,这使用了最令人烦恼的解析,所以我的第二个问题的答案应该是“是的,它使用了最令人烦恼的解析”,不是吗?或者我错过了什么。 (2认同)
  • @Anya 再说一遍,我不明白你的问题。C++ 的语法中存在明显的歧义。[dcl.ambig.res] 规则解决了这些歧义。当没有意识到这种歧义的程序员期望解决方案有所不同时,他们会感到困惑。MVP 是这种模糊性的一个复杂(最令人烦恼)的例子。这些歧义并不是我们“需要”的。当我们遇到这些歧义时,我们需要理解它们才能克服问题。 (2认同)
  • @Anya这不是一个规则,它是一个有时令人惊讶的现象的名称,以便能够谈论它。之所以称为“令人烦恼”,是因为解决歧义可能会令人烦恼。无数程序员花费了数小时试图弄清楚为什么编译器认为明显的变量声明声明了一个函数。 (2认同)