繁体   English   中英

当使用复制构造函数并且存在虚函数时,错误“在所有控制路径上递归”

[英]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)再次复制自身,再次......直到堆栈溢出。

当你没有Bvirtual 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM