【问题标题】:Error "recursive on all control paths" when copy constructor is used and virtual function present使用复制构造函数且存在虚函数时出现“在所有控制路径上递归”错误
【发布时间】:2013-04-04 00:12:47
【问题描述】:

下面的错误让我很困惑。这是一段更复杂的代码。我觉得很奇怪,只有模板化构造函数和虚方法同时存在才会导致错误,并且只有在复制初始化对象时才会发生错误。

有人有想法吗?谢谢。

    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;
    }

【问题讨论】:

    标签: c++ templates visual-c++ multiple-inheritance virtual-functions


    【解决方案1】:

    你所拥有的是一个令人讨厌的copy elision 和一个复制参数的构造函数。

    首先,让我们澄清一个误解:A a = c; 等同于 A a; a = c;。第一个调用复制ctor,第二个调用赋值运算符。使用this code sample亲自查看。

    构造函数A::A&lt;T&gt;(T) 可以在调用时复制T。不幸的是,如果您使用A 参数(或在您的示例中为C,即A)调用它,该参数将尝试复制自身,它再次调用A::A&lt;T&gt;(T),它再次复制自身,再次......直到堆栈溢出。

    B 中没有virtual void f() 时,为什么不会发生这种情况?这是复制省略的副作用,它是一个依赖于实现的特性。拥有虚拟方法可能足以让视觉工作室决定不删除副本,但无论如何你不应该依赖它。这就是为什么你是strongly advised not to have observable side-effects for copy ctors

    以防万一您正在寻找解决方案,您可以通过更改 A::A&lt;T&gt;(T) 来删除副本以获取参考,例如 A::A&lt;T&gt;(T&amp;)。更好的是,使用 const T&amp;,因为这有助于确保 ctor 中没有副作用(因为您无法修改 T)。

    【讨论】:

    • 感谢您的完整,确实我应该使用参考。
    • 技术上它不是一个copy-constructor,而是一个conversion-constructorcopy-constructor 采用与源相同类型的对象,而 conversion-constructor 采用不同类型的对象。模板构造函数不能是 copy-constructor
    • @DavidRodríguez-dribeas 谢谢。更准确地说,只有模板构造函数的特化(TA)是复制构造函数。
    • 没有赋值构造函数这样的东西。 A a; a = c; 调用默认构造函数赋值运算符
    • @CongXu。不可以。模板构造函数不能是复制构造函数,无论多么专业化或参数类型如何。
    【解决方案2】:
        A a=c; // this results in A::A(C c) template constructor instantiation.
    

    之后是递归,因为要复制,你需要复制,你需要复制.... :)

    如需正确使用,请参阅this

    【讨论】:

      猜你喜欢
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-26
      • 2018-08-26
      • 1970-01-01
      相关资源
      最近更新 更多