最令人烦恼的数组访问解析

Most vexing parse with array access

在查看一些 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* 和 returns std::stringstream.

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

直觉上我认为 argv[0] 是对 argv 的明确访问。

原因是因为在函数声明的上下文中,编译器会将 std::string(argv[0]) 解释为 std::string argv[0],即零的 声明 大小数组作为函数参数 named argv(遮盖 main 中的 argv,因为这是一个不同的范围),这相当于array-to-pointer-decay.

的指针

因此,std::stringstream ss(std::string(argv[0]));等同于std::stringstream ss(std::string* argv);

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

我相信这遵循 "declaration syntax is like expression syntax" 原则,并且 "array" 参数是指针这一事实。

以下数组声明是等效的:

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)