在以下代码中:
int foo(const int& f) //version 1
{
int g = f;
return int(foo(g)); // calls itself, turning into SO
}
int& foo(int& f) //version 2
{
f *= -1;
return f;
}
int main()
{
int f = 11;
cout << foo(f) << endl;
cout << foo(22) << endl;
}
第一个cout按预期打印-11; f是左值,因此它绑定到 foo 的第二个版本(虽然它也可以绑定到第一个版本,第二个版本它是更好的匹配)。
foo
的第二次调用是使用右值作为参数,因此唯一可行的foo
版本是第一个。到现在为止还挺好。在foo
的第一个版本中,我制作了参数的副本,因此我可以调用第二个版本(带有左值)并在调用第二个版本后返回它的副本foo
。事情是这会变成堆栈溢出;仍然会调用foo
的第一个版本。
有人可以向我解释为什么会这样吗?我希望g
的第一个版本中的foo
在作为参数传递时绑定到foo
的第二个版本。
答案 0 :(得分:10)
这很简单 - foo
此时仅表示foo(const int& f)
。没有第二选择。还没。切换定义。或者将它们分开:
int foo(const int& f);
int& foo(int& f);
int main()
{
int f = 11;
cout << foo(f) << endl;
cout << foo(22) << endl;
}
int foo(const int& f) //version 1
{
int g = f;
return int(foo(g)); // calls itself, turning into SO
}
int& foo(int& f) //version 2
{
f *= -1;
return f;
}
答案 1 :(得分:2)
foo的第一个声明不知道第二个的存在。试试这个:
int foo(int& f);
int foo(const int& f) //version 1
{
int g = f;
return int(foo(g)); // calls itself, turning into SO
}
答案 2 :(得分:1)
编译器到达行时:
return int(foo(g))
它不知道您的重载版本2.将原型声明添加到文件的顶部:
int foo(const int& f);
int& foo(int& f);
这样编译器就会知道版本2是否存在,并且可以在编写foo
时调用它。