不寻常的析构函数

时间:2013-10-28 09:48:22

标签: c++ constructor destructor copy-constructor

我遇到一个奇怪的问题,实例化一个生活在类中的结构,在构造中它调用析构函数(多次),甚至调用父对象析构函数。

具有结构的类:

class Model {

public:
     struct StepModelIO {
         StepModelIO(Model model, ...) {DoConstruction(Model model, ...);}

         StepModelIO(const StepModelIO &other) {DoConstruction(Model model, ...); }

         ~StepModelIO() {}

         DoConstruction() {
             ...
         }
    }
    Model(...) {
       ...
    }

    Model(const Model &other) {DoConstruction(...);}

    ~Model() {
        ...
    }
private:
    DoConstruction(...) {

    }

}

通话功能:

void main() {

    Model::StepModelIO stepArgs = Model::StepModelIO(...);

}

生成的一组调用,其中'object'为StepModelIO,'parent'为Model

  1. 构建父w /复制构造函数
  2. 构造对象
  3. 破坏父母
  4. 构造具有复制构造函数的对象
  5. 构建父w /复制构造函数
  6. 构造对象
  7. 破坏父母
  8. 破坏对象
  9. 破坏对象(再次......)
  10. 破坏父母
  11. 不出所料,在这一切发生之后,所得到的结构(StepModelIO)并未处于良好状态,并且这条路似乎很荒谬。我有这样的结构在父模型对象中使用相同的泛型,这可以解释一些问题。

    我曾尝试(或许是天真的)在构造函数和析构函数中使用“三规则”,但我可能会严重阻止它。

    修改:完整代码

    template<typename U, typename V>
    class Model{
    
    public:
    
        struct StepModelIO {
            Model<U, V> model;
            U u;
            V v;
    
            StepModelIO() {}
    
            StepModelIO(Model<U, V> model, U u, V v) {
                this->model = model;
                this->u = u;
                this->v = v;
            }
    
            StepModelIO (const StepModelIO &other) {
                StepModelIO(other.model, other.u, other.v);
            }
    
            ~StepModelIO() {
            }
        };
    
        Model(char * libraryPath) {DoConstruction(libraryPath);}
    
        Model() {}
    
        Model (const Model &other) {
            DoConstruction(other.m_LibraryPath);
        }
    
        ~Model() {
            this->Stop();
        }
    
        void Init() {
            if (!this->m_Initialised) {
                this->ModelInit();
                m_Initialised = true;
            }
        }
    
        void Stop() {
            if (this->m_Initialised) {
                this->ModelStop();
                m_Initialised = false;
            }       
        }
    
        void Restart() {
            this->ModelRestart();
        }
    
        void Step(U u, V v) {
            ModelStep(u, v);
        }
    
    private:
    
        char* m_LibraryPath;
        HINSTANCE m_ModelDLL;
    
        bool m_Initialised;
    
        typedef int (__cdecl * EmptyModelFunctionPointer)(); // Interpret integer as C code pointer named 'EmptyModelFunctionPointer'
        typedef int (__cdecl * ModelFunctionPointer)(U u, V v);
    
        EmptyModelFunctionPointer ModelInit;
        EmptyModelFunctionPointer ModelStop;
        EmptyModelFunctionPointer ModelRestart;
        ModelFunctionPointer ModelStep;
    
        virtual void DoConstruction(char * libraryPath){
            this->m_Initialised = false;
            this->m_LibraryPath = libraryPath;
            this->m_ModelDLL = LoadLibrary(libraryPath);
            this->ModelInit = GetFunction<EmptyModelFunctionPointer>(m_ModelDLL, "Init");   
            this->ModelStop = GetFunction<EmptyModelFunctionPointer>(m_ModelDLL, "Stop");
            this->ModelRestart = GetFunction<EmptyModelFunctionPointer>(m_ModelDLL, "Restart");
            this->ModelStep = GetFunction<ModelFunctionPointer>(m_ModelDLL, "Step");
        }
    
        template<typename pointerType>
        pointerType GetFunction(HINSTANCE modelLibrary, char * functionName){
            return (pointerType)GetProcAddress(HMODULE (modelLibrary),functionName);
        }
    };
    

    呼叫者:

    StepModelIO<Type_1*, Type_2*> stepArgs = StepModelIO<Type_1*, Type_2*>(newModel, &a, &b[0]);
    

2 个答案:

答案 0 :(得分:2)

您按值传递事物,这将导致构造和销毁临时对象。改为通过const引用传递它们。

变化

  StepModelIO(Model model, ...) 

  StepModelIO(const Model &model, ...) 

您现在已经更改了代码。我想你真的想要这个。

 StepModelIO(const Model<U, V> &model, const U &u, const V &v)

答案 1 :(得分:1)

我在类StepModelIO中注意到你有一个成员Model<U, V> model;所以对于每个类StepModelIO的实例,模型的析构函数也会被篡改;第一个~StepModelIO()和第二个~Model<U, V>()

所以给出你提供的代码:

Model::StepModelIO stepArgs = Model::StepModelIO(...);

这有两个StepModelIO类型的对象。一个是右边的开(右边),第二个是stepArgs

首先调用右边那个的析构函数,得到:

1:Destruct StepModelIO

2:Destruct Model

当stepArgs发生破坏时:

3:Destruct StepModelIO

4:Destruct Model