-1

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

具有结构的类:

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(...);

}

调用的结果集,“对象”是StepModelIO,“父”是Model

  1. 使用复制构造函数构造父级
  2. 构造对象
  3. 破坏父级
  4. 使用复制构造函数构造对象
  5. 使用复制构造函数构造父级
  6. 构造对象
  7. 破坏父级
  8. 破坏对象
  9. 破坏对象(再次...)
  10. 破坏父级

不出所料,StepModelIO在这一切发生之后,生成的结构 (a ) 状态并不好,而且路径似乎很荒谬。我有这样的结构,以便在父模型对象上使用相同的泛型,这可以解释一些问题。

我曾尝试(也许是天真地)在构造函数和析构函数上使用“三规则”,我可能把它搞砸了。

编辑:完整代码

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]);
4

2 回答 2

2

You're passing things by value, which will result in temporary objects being constructed and destructed. Pass them by const reference instead.

change

  StepModelIO(Model model, ...) 

to

  StepModelIO(const Model &model, ...) 

You've now changed the code. So you really want this, I think.

 StepModelIO(const Model<U, V> &model, const U &u, const V &v)
于 2013-10-28T10:01:38.100 回答
1

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

因此,鉴于您提供的代码:

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

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

首先调用右边那个的析构函数导致:

1:Destruct StepModelIO

2:Destruct Model

当 stepArgs 发生破坏时:

3:Destruct StepModelIO

4:Destruct Model

于 2013-10-28T10:16:42.787 回答