【问题标题】:How does this declaration invoke the Most Vexing Parse?这个声明如何调用最令人烦恼的解析?
【发布时间】:2014-02-07 10:12:38
【问题描述】:

考虑以下程序:

#include <fstream>

struct A {};

int main(int argc, char** argv) {
    A a(std::fstream(argv[1]));
}

C++1y 模式下的 Clang 估计 MVP 被调用使得 a is parsed as a function declaration:

clang++ -std=c++1y -O3 -Wall -Wextra -pedantic-errors -pthread main.cpp && ./a.out

main.cpp:6:8: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]

    A a(std::fstream(argv[1]));

       ^~~~~~~~~~~~~~~~~~~~~~~

main.cpp:6:9: note: add a pair of parentheses to declare a variable

    A a(std::fstream(argv[1]));

        ^

        (                    )

我理解 MVP,但在这种情况下不是:argv[1] 显然是一个表达式,并且它之前没有类型,那么如何将这一行解析为函数声明?

argv[1] 上的语义解释是否会在编译器已经选择将行解析为函数声明之后才会将该行作为对象声明消除歧义?或者它是一个 Clang 错误?还是通过对我缺少的标记 argv [ 1 ] 的一些解释完全正常?

【问题讨论】:

    标签: c++ most-vexing-parse


    【解决方案1】:

    我认为它被解析为

    A a(std::fstream argv[1]);
    

    即一个函数,它接收一个包含 1 个std::fstream 的数组,其中多余的括号是多余的。

    当然,实际上,数组参数会衰减为指针,所以你最终得到的语义是:

    A a(std::fstream* argv);
    

    【讨论】:

    • 啊,是的,就是这样。我总是想念这个案子!谢谢:)
    • -1。这部分是错误的>>a function that takes in an array of 1 std::fstream。参数不是数组,是指针!
    • @Nawaz:参数可以是数组(它只是一个占位符,您可以这样声明,没问题),但参数不能(因为参数是值,而值可以传递,但数组不能传递)。
    • @Nawaz: "[C++11: 8.3.5/5]: 确定每个参数的类型后,将“T的数组”或“返回T的函数”类型的任何参数调整为“指向T的指针”或“指向返回 T 的函数的指针”。” 这意味着参数以T[N] 开始,更改为T*,之后参数当然只能采用T* 类型因为这就是参数类型变成的样子。
    • @Nawaz:不,我的回答正是我告诉你的,也是标准所说的。和你辩论是徒劳的,因为你是在用标准来辩论,所以我现在就停下来。
    【解决方案2】:

    括号是多余的。以下都是声明:

    T a;
    T (a);
    T ((a));
    T (((a))));
    

    这些也是:

    T a[1];
    T (a[1]);
    T ((a[1]));
    T (((a[1]))));
    

    是这样的:

     A a(std::fstream(argv[1]));
    

    等同于:

     A a(std::fstream argv[1]);
    

    等同于:

     A a(std::fstream *argv);
    

    希望对您有所帮助。

    【讨论】:

    • 这些不是大括号。
    • 这些不是大括号,它们都不会调用 MVP,因为您没有为那个假设的单个参数命名类型。我什至会说括号的这个属性在这种情况下并不能证明很多,因为参数表达式很容易与参数列表有不同的规则。
    • 我并不是说T a; 的声明调用了MVP。那是用来解释parens的多余作用的!
    • 我理解,但是由于参数列表的行为可能与参数列表不同,因此它并不能真正证明这个问题的任何内容。即使事实证明,他们表现不同;)我只是很挑剔。
    • @LightnessRacesinOrbit:我不是说这是证据。请不要阅读我没有说的内容:P...各种声明的目的是证明即使在简单的声明中,extra parens 的行为也是相同的! ...再说一遍,因为简单的声明很容易记住,所以它可以帮助我(或像我这样的程序员)理解复杂的声明。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-20
    相关资源
    最近更新 更多