最令人烦恼的数组访问解析
Most vexing parse with array access
在查看一些 C++03 代码时,我发现了一个 最令人烦恼的解析 的实例,这让我感到困惑:
#include <sstream>
#include <string>
int main(int, char** argv)
{
std::stringstream ss(std::string(argv[0]));
}
在上面的代码片段中,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)
在查看一些 C++03 代码时,我发现了一个 最令人烦恼的解析 的实例,这让我感到困惑:
#include <sstream>
#include <string>
int main(int, char** argv)
{
std::stringstream ss(std::string(argv[0]));
}
在上面的代码片段中,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)