最令人烦恼的解析与阵列访问

时间:2017-12-12 15:19:35

标签: c++ c++03 most-vexing-parse

在查看一些C ++ 03代码时,我发现了一个让我感到困惑的最烦恼的解析的实例:

#include <sstream>
#include <string>

int main(int, char** argv)
{
    std::stringstream ss(std::string(argv[0]));
}

live example on wandbox

在上面的代码段中,ss是一个函数的声明,它接受std::string*并返回std::stringstream

std::string(argv[0])如何被解析为std::string*

直觉上我认为argv[0]明确无误访问argv

2 个答案:

答案 0 :(得分:18)

原因是因为在函数声明的上下文中,编译器会将std::string(argv[0])解释为std::string argv[0],即将零大小数组的声明解释为函数参数命名为 argv(从argv掩盖main,因为这是一个不同的范围),然后等同于 array-的指针到指针衰减

因此,std::stringstream ss(std::string(argv[0]));表示与std::stringstream ss(std::string* argv);

相同

编辑:由于它在注释中被正确注释,零大小的数组声明在C ++中无效,导致程序格式错误。使用-pedantic标志(GCC和clang)编译此代码时,将发出警告。 Visual Studio甚至会产生编译错误。对于除0以外的任何其他数组索引,上述论证仍然有效。

答案 1 :(得分:7)

我认为这来自&#34;声明语法就像表达式语法&#34;原则,以及&#34;阵列&#34;参数是指针。

以下数组声明是等效的:

int x[1];
int (x)[1];
int (x[1]);

或多或少,因为x[a](x)[a](x[a])是等效表达式。

因此,

std::stringstream ss(std::string(argv[0]))

                 <=>

std::stringstream ss(std::string argv[0])

                 <=>

std::stringstream ss(std::string* argv)