Vit*_*meo 21 c++ most-vexing-parse c++03
在查看一些C++ 03代码时,我发现了一个让我感到困惑的最令人烦恼的解析实例:
#include <sstream>
#include <string>
int main(int, char** argv)
{
    std::stringstream ss(std::string(argv[0]));
}
在上面的代码片段中,ss是一个函数的声明,它接受std::string*并返回std::stringstream.
怎么std::string(argv[0])解析为std::string*?
直觉上,我认为这argv[0]是明确无误的访问argv.
Jod*_*cus 18
原因是因为在函数声明的上下文中,编译器将解释std::string(argv[0])为std::string argv[0],即一个零大小数组的声明作为命名 的函数参数argv(遮蔽了argvfrom main,因为这是一个不同的范围),这相当于由一个指针阵列到指针衰变.
因此,std::stringstream ss(std::string(argv[0]));意思相同std::stringstream ss(std::string* argv);
编辑:由于它在注释中被正确注释,零大小的数组声明在C++中无效,导致程序格式错误.使用-pedantic标志(GCC和clang)编译此代码时,将发出警告.Visual Studio甚至会产生编译错误.对于除0以外的任何其他数组索引,上述论证仍然成立.
我相信这是从"声明语法就像表达式语法"原理,以及"数组"参数是指针的事实.
以下数组声明是等效的:
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)