我遇到了以下代码的奇怪行为,同时使用g ++ 4.4.3进行了初始化。
int main()
{
int x(int());
int y = int();
cout << x << " " << y << endl;
}
结果是:
1 0
“y”的值如预期的那样为0,但x的值奇怪地为“1”!
在VS2008上产生以下链接错误(函数声明,但没有定义):
unresolved external symbol "int __cdecl x(int (__cdecl*)(void))"
任何人都可以解释这个奇怪的g ++行为吗?
答案 0 :(得分:24)
int x(int());
被解析为函数声明。
它声明了一个名为x
的函数,返回一个int
并接受一个参数,该函数的函数类型返回int
并且不接受任何参数。
这被称为最令人烦恼的解析。
答案 1 :(得分:13)
为了补充GMan的回答here(x
是一个函数定义),为什么1
。
输出为1
的原因是在调用地std::cout << x
处,函数衰减为指向函数的指针(该语言不允许您将函数作为参数传递给其他函数,与数组一样,执行指向的隐式转换。现在,ostream
没有带有函数指针的重载,编译器尝试选择转换为任何可用的重载。此时它发现最佳转换序列是bool
并且它打印1
(指针不是0)。
您可以通过更改行为来检查此问题,您可以使用std::cout << std::boolalpha << x
,这将打印true
而不是1
。另外,值得注意的是VS是正确的,因为表达式std::cout << x
需要取x
的地址,然后函数使用并且程序是如果没有该功能的定义,则形成不良。您可以通过提供定义再次检查:
int f() {}
int main() {
int x(int()); // 1
x( &f ); // 2
}
int x( int(*)() ) { // 3
std::cout << "In x" << std::endl;
}
我已在function
(1)的定义中手动执行从pointer-to-function
到x
的转换以及使用参数f
(2)的调用 - 请注意,1中的声明和3 中的定义是相同的签名,如果不这样做,编译器将执行&
中的x( &f )
。
答案 2 :(得分:4)
添加更多parens:
int main()
{
int x((int()));
int y = int();
cout << x << " " << y << endl;
}
现在x是一个int,而不是一个函数。
答案 3 :(得分:3)
正如其他人所说,x
是一个功能声明。由于没有为函数指针类型定义预定义的ostream插入器,因此g ++似乎使用隐式bool转换(用于检查函数指针是否为NULL)来找到输出它的方法。
x
从未被定义,因此它无法完成链接。我怀疑在这种情况下g ++足够聪明,可以看到函数永远不会被调用,因此不用担心链接。
您可以尝试在代码中添加函数int x(int(*)()) { return 0xdeadbeef; }
的虚拟定义,然后查看MSVC对其执行的操作。
答案 4 :(得分:2)
C ++将第一个解释为函数的声明。
答案 5 :(得分:1)
这个
int x(int());
实际上是一个函数声明,输入是以下签名的函数
int fn(void)
传递给std::cout <<
的函数指针转换为bool(1),因为它是非NULL指针。