【问题标题】:calling constructor of the class in the destructor of the same class在同一个类的析构函数中调用类的构造函数
【发布时间】:2011-02-15 21:30:12
【问题描述】:

专家!!我知道这个问题是最糟糕的问题之一,但我仍然敢于敞开心扉,希望我能向所有人学习。

我在例行程序中尝试了一些示例,并做了一件可怕的事情,我从同一个类的析构函数中调用了类的构造函数。

我真的不知道在实际编程中是否需要这样做,我想不出我们真正需要在析构函数中调用函数/CTOR 的任何实时场景。通常,析构函数用于清理。

如果我的理解是正确的,为什么编译器不抱怨?这是因为它出于某些充分的理由而有效吗?如果有,它们是什么?

我尝试了 Sun Forte、g++ 和 VC++ 编译器,但没有人抱怨。\

编辑:我感谢大家的回答,我想我的观点没有说清楚,我知道结果,它会以递归方式结束,程序可能会崩溃,但问题实际上是关于 Destructor 允许创建一个对象。


using namespace std; class test{ public: test(){ cout&lt;&lt;"CTOR"&lt;&lt;endl; } ~test() {cout<<"DTOR"<<endl; test(); }};

【问题讨论】:

    标签: c++ oop constructor g++ destructor


    【解决方案1】:

    当以下运行时

    test();
    

    您构造了一个临时(新)对象,当控制“经过分号”时立即销毁该对象,调用该临时对象的析构函数,构造另一个临时对象等,因此您会陷入无休止的死亡螺旋递归调用会导致堆栈溢出并使您的程序崩溃。

    禁止析构函数创建临时对象将是荒谬的 - 它会严重限制您可以正确的代码。这也没有任何意义 - 析构函数正在销毁 当前 对象,而那些临时对象与它完全无关,因此对它们实施这样的约束是没有意义的。

    【讨论】:

    • 但是有一个无限递归,对吧?临时对象被销毁,这就创建了一个临时对象,被销毁了,...不是吗?
    • @sharptooth:正确,我在上一篇文章中从你那里学到了一些东西,但这次我的问题是,当我们在 DTOR 中没有任何具体的事情可以做时,为什么编译器不会抱怨。
    • @dicaprio:这并不奇怪,因为该代码是完全合法的。您可以在析构函数运行时合法地创建任何临时对象。
    • @aioobe:是的,那是无限递归。
    • 好吧,我不得不半信半疑地同意这样做是合法的,但是有什么真正的用处吗?你有任何可以支持的真实例子吗?我想了解的是,如果他们支持某些东西并且是合法的,那么它应该有用吗?那是什么?
    【解决方案2】:

    据我了解,您只是在析构函数中实例化新的 test 对象并保持原样。

    【讨论】:

      【解决方案3】:

      由于无限递归,这段代码给了测试实例一个很大的尺寸,实际上很快就会产生堆栈溢出:

      #include <iostream>
      using namespace std;
      class test{
         public:
          int a[10000];
          test(){
           }
      
      ~test() {
       test();
       }};
      
      int main() {
          test t;
      }
      

      C++ 不要求对无限递归发出警告,一般情况下很难检测到。

      【讨论】:

      • Neil,我记得你之前在回复我 cmets 时说过,当调用 CTOR/DTOR 时,编译器会发出额外的东西,而在这种情况下,这似乎是绝对没有必要的,我相信它应该是如果没有实际用处,请避免。
      • @dicaprio 编译器可以优化调用,或者再次选择不这样做。仅仅因为你可以看到调用是没有意义的,并不意味着编译器可以。
      • @dicaprio:代码也不是毫无意义的——它要求编译器构造一个具有非平凡析构函数的临时对象,所以编译器就是这样做的。
      • @dicaprio 事实上,在启用 -O3 优化的情况下,g++ 确实优化了构造函数调用,并且程序在没有堆栈溢出的情况下运行。
      【解决方案4】:

      静态分析工具是应该抱怨的东西。对我来说,您的情况与以下情况没有太大不同:

      void foo();
      void bar()
      {
         foo();
      }
      void foo()
      {
         bar();
      }
      

      我不知道有没有编译器会抱怨上面的代码,但是这个例子比你的简单得多,可能还有很多其他的。

      编辑: 在您的情况下,问题要简单得多。这是一个普通的无限递归,因为你的析构函数的想法有点像这样:

         ~test()
         {
            cout<<"DTOR"<<endl;
            test tmp();
            tmp.~test(); // infinite recursion.
         }
      

      【讨论】:

      • 绝对简单的好例子,谢谢。我从来没有试过这个。
      【解决方案5】:

      我看不出它为什么应该是非法的,但我承认我正在努力想出一个体面的例子来说明我为什么要这样做。要使其“工作”,您需要有条件地调用 c'tor 而不是无条件地调用。

      【讨论】:

        猜你喜欢
        • 2023-04-03
        • 2014-08-01
        • 2012-06-22
        • 2014-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多