我正在使用从此处获取的状态模式编写有限状态机:
我在这里实现了它:
回想一下我的想象,你有这种情况:
//MAIN MACHINE
class machine{
public:
void handle(){
_state->handle();
}
void setStatePtr(AbstrState *state){
_state = state;
}
private:
AbstrState* _state;
};
//BASE STATE
class AbstrState {
public:
AbstrState(machine* m){
_context = m;
}
virtual void handle() = 0;
protected:
machine *_context;
};
//ACTUAL STATES
class ONState : AbstrState{
public:
ONState(machine *m) : AbstrState(m) {}
void handle(){
if(BUTTON_PRESSED){
_context->setStatePtr( new OFFState(_context));
}
}
};
class OFFState : AbstrState{
public:
OFFState(machine *m) : AbstrState(m) {}
void handle(){
if(BUTTON_PRESSED){
_context->setStatePtr( new ONState(_context) );
}
}
};
使用setStatePtr(new OFFState(&machine))
我的问题在这里提出:因为我正在使用new运算符,所以我应该在某处调用delete但是在哪里?我尝试在setStatePtr函数中执行:
void setStatePtr(.. s){
delete _state;
_state = s;
}
但它不起作用。
我没有定义任何指针p * = new p();所以我不知道在哪里删除任何删除。我的问题更具有道德性,所以请不要建议其他实施或使用,因为我仍会有同样的疑问:)
当我做foo(新事物)时,我在哪里打电话给删除?
提前感谢,
安德烈
答案 0 :(得分:2)
旧方法是以这种方式实现该方法:
void setStatePtr(AbstrState *state){
if( _state != state ) {
delete _state;
_state = state;
}
}
但正确的方法是使用智能指针:
class machine{
public:
void setStatePtr( std::unique_ptr<AbstrState> state){
_state = std::move( state );
}
private:
std::unique_ptr<AbstrState> _state;
};
这样你就有两个好处:
答案 1 :(得分:0)
你的错误是成员setStatePtr()。指针来自哪里?它所引用的对象什么时候被删除?我们只是不知道。
这就是为什么C ++现在拥有您拥有的对象的唯一指针,以及多个实体引用的对象的共享指针。你刚才提到的指针很简单。通常,类似于州的东西会被深层复制。该集接受一个const引用,并分配给一个不是指针而是完整对象的成员。
除了实现像STL本身这样的低级结构外,new和delete在C ++中不再使用了很多。
答案 2 :(得分:-1)
谁调用new,谁调用delete。 通常,函数foo可能不会调用delete,因为无法判断指针是否由new分配(除非以这种方式明确指定foo的使用)。
但如果你使用RAII习语,那将是另一个故事。这似乎就是这种情况。然后你的班级应该在复制分配,销毁或任何其他应该“免费”的操作中调用delete。较旧的资源。
顺便说一句,以下划线(_)开头的名称保留给实现,因此你不应该使用它。