使用'this'指针删除

时间:2012-07-24 13:20:19

标签: c++ this delete-operator

我正在为学校做一个项目。 它模拟学生从自动售货机购买苏打水。 有一个名为Card的类,它是Student类中的成员。 也就是说,

每个学生都有一张卡片,这是有意义的。

class Student {
public:
    Student( Office &cardOffice );
    ~Student();
    bool action();
    private:
    Office* studentOffice;          // stores cardoffice.
    Card* card;                 // stores card
};

学生卡是通过调用studentOffice.create()函数创建的。该函数返回一张卡片。

Card* Office::create( int id, int money ) {
    Card* card = new Card();
    card->id = id;
    card->amount = money;
    return card;
}

学生在VendingMachine类中调用一个名为action()的函数来购买食物。 VendingMachine中的buy函数返回VendingMachine类中Status enum的类型枚举。

有一个prng,从0到9生成一个随机数。作业说,学生卡被摧毁的概率为十分之一。并且他/她将在下次调用student.action()时获得一个新的。

VendingMachine::Status VendingMachine::buy(Card* &card)
{
    if(prng(9) == 0) // generates number from 0-9
    {
        delete card;
    }
    return status;
}

最初,我正在考虑检查学生的action()例程以查看该卡是否为NULL(如果已删除),并在发生这种情况时创建一个新卡。但是,我知道代码到达删除卡部分,但在检查卡是否为NULL时失败。所以这必须意味着卡不是空的,这意味着删除不起作用。

但我也注意到传入的卡是

类型
Card* &card

我当时正在考虑使用带有“this”指针的调用,因为我知道学生调用了这个例程,“this”将指向根据以下内容调用它的对象:

它指向调用成员函数的对象。 来自http://msdn.microsoft.com/en-us/library/y0dddwwd(v=vs.80).aspx

但是,如果我这样做:

if(prng(9) == 0)
{
    delete this->card;
}

运行makefile时出现此错误:

  

错误:类VendingMachine没有名为card的成员

这是真的,但事实并非如此。编译器是否假设VendingMachine会调用此方法?因为学生的确如此。

  1. 也许我应该在每台自动售货机上添加一名学生,然后从该会员中删除该卡?我强烈不愿意这样做,因为有多个学生,这意味着如果他们被分配到这台自动售货机,我需要将它们全部存储起来。虽然,如果归结为它,我可以这样做。

  2. 如果发生了删除卡,但该卡不是NULL,那么当我删除该卡时究竟发生了什么?

  3. 如何删除该卡?

  4. 谢谢!

    编辑:应用更改后,代码现在是:

    if(prng(9) == 0)
    {
        cout << "Destroying card" << endl;
        delete card;
        card = NULL;
        cout << "Card Destroyed" << endl;
        }
    

    不幸的是,我遇到了段错误,这可能是因为我正在访问一张不存在的被破坏的卡片。因为显示销毁卡和销毁卡,

    但是我在这次电话会议中的cout没有出现:

        if(card == NULL)
        {
            cout << "CARD DESTROYEDADJIWJDOQIODJWDIOJWQODWODIQODJWJOWDW" << endl;
            card = studentOffice->create(id, 5);
        }
    

    显然卡仍然不是NULL?这很奇怪。

    EDIT2:我想我知道问题所在,以及为什么会出现段错误。现在正在努力。

    EDIT3:通过重新排列卡被销毁时使用卡的电话的顺序来解决。

4 个答案:

答案 0 :(得分:3)

在方法buy中,您应该删除指针并将其设置为NULLdelete不会自动将指针设置为NULL):

VendingMachine::Status VendingMachine::buy(Card* &card)
{
    if(prng(9) == 0) // generates number from 0-9
    {
        delete card;
        card = NULL;
    }
    return status;
}

这就是指针通过引用传递的原因(因此您可以将NULL分配给原始指针而不是它的副本。)

除此之外,this->card无法编译,因为card属于类Student,而不属于VendingMachine。从VendingMachine的角度来看,它只是方法buy中的一个参数。

答案 1 :(得分:2)

当您致电delete时,没有任何内容可以说您将其调用的指针设置为NULL。如果要在删除后确保它为NULL,则应在删除后自行完成。

答案 2 :(得分:1)

除了@ betabandido的答案之外,您始终可以在宏中定义删除方法来为您执行此操作。

#define DELETE(ptr) ( delete ptr; ptr = NULL;) 

虽然不可否认,这几乎总是一个坏主意,特别是当你在学校时,你应该养成在删除指针后将指针设置回NULL的习惯。

此外,这可能会导致您产生错误的安全感:

void MethodDeleteThis(void* item)
{
   delete item;
   item = NULL;
}

没有真正解决问题,因为item是传递指针的COPY。因此,虽然delete可能释放了item指向的对象,但将指针设置为NULL不会将传递给该方法的指针的值更改为NULL。解决这个问题的唯一方法是采用双指针或通过引用传递指针 - 这通常看起来很奇怪而且不合适。我见过gobject和gstreamer这样做。

我注意到,许多库总是在有任何分配或释放时返回指针,以便您可以更可靠地检索和测试值。

答案 3 :(得分:1)

正如其他人所指出的,每当你delete指针时,你也应该立即将它设置为NULL。不要使用宏,养成这样做的习惯。

现在,试着戴上我的最佳实践帽子:

我总是发现在做这类事情时传递双指针更有用,而不是通过引用传递指针:

VendingMachine::Status VendingMachine::buy(Card** card) {
    // ...
    if (NULL == *card) {
        delete *card;
        *card = NULL;
    }

这迫使你在代码中稍微区别对待指针,但好处是你操作指针更明显,它消除了方法调用中的歧义:

  vend.buy(card);  // Pointer reference
  vend.buy(&card); // Pointer to pointer

通过第二次调用,您只需通过查看该方法即可修改card的值。