关于c ++:在这种情况下我应该在哪里调用delete?

Where should I call delete in this case?

本问题已经有最佳答案,请猛点这里访问。

我正在使用从这里获取的状态模式对有限状态机进行编程:

状态模式

我已经在这里实现了它:

我的机器Github

回想一下我曾经想象过的情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//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))初始化的。

我的问题出现在这里:由于我使用了新的运算符,我应该在哪里调用delete?我尝试了setstateptr函数,它执行以下操作:

1
2
3
4
void setStatePtr(.. s){
    delete _state;
    _state = s;
}

但它不起作用。

我没有定义任何指针p*=new p();所以我不知道在哪里调用任何删除。我的问题更具道德性,因此请不要建议其他实施或惯例,因为我仍然有同样的疑问:)

当我做foo(新事物)时,我在哪里可以调用delete?

提前感谢,

安德莉亚


旧方法是通过以下方式实现该方法:

1
2
3
4
5
6
void setStatePtr(AbstrState *state){
   if( _state != state ) {
       delete _state;
       _state = state;
   }
}

但正确的方法是使用智能指针:

1
2
3
4
5
6
7
8
9
10
11
class machine{
public:

    void setStatePtr( std::unique_ptr<AbstrState> state){

        _state = std::move( state );
    }

private:
    std::unique_ptr<AbstrState> _state;
};

这样您就有两个好处:

  • 资源自动管理,必要时销毁
  • 您的方法签名清楚地表明它将获得所传递对象的所有权,当您传递原始指针时,它是不清楚的,并且您必须在文档中解释这一点,这很容易出错。


您的错误是成员setStateDepr()。那个指针是从哪里来的?它所引用的对象何时被删除?我们只是不知道。

这就是为什么C++现在有了独特的指针,对于你拥有的对象,以及对于多个实体引用的对象的共享指针。你刚才提到的指针很简单。通常情况下,类似状态的东西会被深度复制。该集合接受一个常量引用,并将其分配给一个不是指针而是完整对象的成员。

C++中不再使用新的和删除,除了实现像STL本身那样的低级结构。


谁叫新的,谁叫删除。通常情况下,函数foo不能调用delete,因为我们无法判断指针是否由new分配(除非这样明确指定foo的用法)。

但如果你使用的是RAII成语,那就另当别论了。这里似乎是这样。然后您的类应该在副本分配、销毁或任何其他应该"释放"旧资源的操作期间调用delete。

顺便说一下,名称以下划线开头是为实现保留的,因此您不应该使用它。