![](/img/trans.png)
[英]“Recursive on All Control Paths” error when implementing factorial function
[英]Error “recursive on all control paths” when copy constructor is used and virtual function present
下面的错误令我感到困惑。 这是一段更复杂的代码。 我觉得很奇怪,只有模板化构造函数和虚方法都存在错误,并且只有在复制初始化对象时才会出错。
有没有人有想法? 谢谢。
class A
{
long *p;
public:
A():p(0)
{
}
template<class T>
A(T val):p(val)// 1
{
}
operator long*()
{
return p;
}
};
class B
{
virtual void f()// 2
{
}
};
class C : public A, public B
{
};
void main()
{
C c;
main()
的下一行是
A a=c;
如果标记为// 1
和// 2
的行都存在,则触发下面的错误:
warning C4717: 'C::C' : recursive on all control paths, function will cause runtime stack overflow
但是当在main()
使用以下内容时,没有错误:
A a;
a=c;
}
你所拥有的是复制省略和构造函数的令人讨厌的汇合,它构成了参数的副本。
首先,让我们澄清一个误解: A a = c;
不等于A a; a = c;
A a; a = c;
。 第一个调用copy ctor,第二个调用赋值运算符。 使用此代码示例自行查看。
无论何时调用,构造函数A::A<T>(T)
都可以复制T
不幸的是,如果你使用A
参数(或在你的例子C
,它是A
)调用它,参数将尝试复制自身,再次调用A::A<T>(T)
再次复制自身,再次......直到堆栈溢出。
当你没有B
的virtual void f()
时,为什么不会发生这种情况呢? 这是copy elision的副作用,它是一个依赖于实现的功能。 拥有虚拟方法可能已经足以让visual studio决定不删除副本,但无论如何你不应该依赖它。 这就是为什么强烈建议您不要为复制者提供可观察到的副作用 。
如果您正在寻找解决方案,可以通过更改A::A<T>(T)
来删除副本以获取引用,例如A::A<T>(T&)
。 更好的是,采用const T&
因为这有助于确保ctor中没有副作用(因为你无法修改T
)。
A a=c; // this results in A::A(C c) template constructor instantiation.
之后它是递归,因为要制作副本,你需要制作副本,你需要制作副本.... :)
如需正确使用,请参阅此
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.