使用复制构造函数和存在虚拟函数时出错"recursive on all control paths"
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;
}
你所拥有的是复制 elision 和一个制作参数副本的构造函数的令人讨厌的汇合。
首先,让我们澄清一个误区:A a = c;
不等同于A a; a = c;
。第一个调用复制 ctor,第二个调用赋值运算符。使用此代码示例亲自查看。
构造函数A::A<T>(T)
可以在调用T
时创建它的副本。不幸的是,如果您使用 A
参数调用它(或在您的示例 C
中,这是一个A
(,该参数将尝试复制自身,这会再次调用A::A<T>(T)
,这会一次又一次地复制自身......直到堆栈溢出。
当您没有B
virtual void f()
时,为什么不会发生这种情况?这是复制 elision 的副作用,复制 elision 是一个依赖于实现的功能。拥有虚拟方法可能足以让Visual Studio决定不删除副本,但无论如何您都不应该依赖它。这就是为什么强烈建议您不要对复制 ctor 产生可观察到的副作用。
以防万一您正在寻找解决方案,您可以通过更改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.
之后是递归,因为要制作副本,您需要制作副本,您需要制作副本:)。
有关正确用法,请参阅此处。
- 访问者访问变体并返回不同类型时出错
- 在Linux for Windows上编译C++代码时出错
- 读取文件的最后一行并输入到链接列表时出错
- 重载操作程序时出错>>用于类中的字符串 memebr
- 调用专用模板时出错"no matching function for call to [...]"
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- LINK 尝试使用 OpenSSL evp aes 256 c++ 时出错
- 在Google Kick start中提交时出错
- 在c++中访问int到类对象的映射时出错
- 分段错误当我试图运行程序时出错
- 使用dynamic_cast和构造函数时出错
- CHECK(调用)函数在Google Colab中出错
- 用pybind11包装C++抽象类时出错
- 为x86而非x64编译时出错
- 从R调用C++函数并对其进行集成时出错
- 这个函数哪里出错了
- C++ 创建包含链表和字符串的对象的链接列表时出错
- 为重写std::exception的库生成swig接口时出错
- 导入/导出变量时出错
- 使用复制构造函数和存在虚拟函数时出错"recursive on all control paths"