Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用';这';指向删除的指针_C++_This_Delete Operator - Fatal编程技术网

C++ 使用';这';指向删除的指针

C++ 使用';这';指向删除的指针,c++,this,delete-operator,C++,This,Delete Operator,我正在为学校做一个项目。 它模拟学生从自动售货机购买苏打水。 有一个叫做Card的班级,它是班级学生中的一员。 就是 每个学生都有一张卡片,这很有意义 class Student { public: Student( Office &cardOffice ); ~Student(); bool action(); private: Office* studentOffice; // stores cardoffice. C

我正在为学校做一个项目。 它模拟学生从自动售货机购买苏打水。 有一个叫做Card的班级,它是班级学生中的一员。 就是

每个学生都有一张卡片,这很有意义

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类中的状态枚举返回类型枚举

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

VendingMachine::Status VendingMachine::buy(Card* &card)
{
    if(prng(9) == 0) // generates number from 0-9
    {
        delete card;
    }
    return status;
}
最初,我想检查student的action()例程,查看卡片是否为空(如果已删除),如果出现这种情况,则创建一个新卡片。但是,我知道该代码会到达删除卡部分,但在检查该卡是否为空时失败。这意味着卡不是空的,这意味着删除无效

但我也注意到传递的卡片是

Card* &card
我当时正在考虑使用一个带有“this”指针的调用,因为我知道这个学生就是所谓的这个例程,“this”将指向调用它的对象,根据:

它指向为其调用成员函数的对象。 从

但是,如果我这样做:

if(prng(9) == 0)
{
    delete this->card;
}
在运行makefile时,会出现以下错误:

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

但事实并非如此。编译器是否假设自动售货机将调用此方法?因为学生是这样做的

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

  • 如果删除卡发生了,但卡不是空的,那么当我删除卡时,到底发生了什么

  • 我该如何删除该卡

  • 谢谢

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

    if(prng(9) == 0)
    {
        cout << "Destroying card" << endl;
        delete card;
        card = NULL;
        cout << "Card Destroyed" << endl;
        }
    
    if(prng(9)==0)
    {
    
    cout在方法
    buy
    中,您应该删除指针并将其设置为
    NULL
    delete
    不会自动将指针设置为
    NULL
    ):

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


    除此之外,
    这张->卡
    不会编译,因为
    属于类
    学生
    ,而不是
    自动售货机
    。从
    自动售货机
    的角度来看,它只是方法
    购买
    中的一个参数,当你调用
    删除
    时,没有什么可以说你调用的指针将其设置为
    NULL
    。如果要确保删除后它为NULL,则应在删除后自己执行此操作。

    除了@betabando的答案外,您还可以在宏中定义一个delete方法来执行此操作

    #define DELETE(ptr) ( delete ptr; ptr = NULL;) 
    
    尽管不可否认,这几乎总是一个坏主意,尤其是当你在学校时,你应该养成在删除指针后将其设置回NULL的习惯

    此外,这可能会让你产生错误的安全感:

    void MethodDeleteThis(void* item)
    {
       delete item;
       item = NULL;
    }
    
    无法真正解决此问题,因为item是传递的任何指针的副本。因此,虽然delete可能已释放item指向的对象,但将指针设置为NULL不会将传递给方法的指针的值更改为NULL。唯一的解决方法是使用双指针或通过引用传递指针这看起来很奇怪,也不合适。不过我见过gobject和gstreamer这样做


    我注意到,如果有任何分配或解除分配,许多库都会返回指针,以便您可以更可靠地检索和测试值。

    正如其他人所指出的,任何时候您
    删除
    指针时,您也应该立即将其设置为
    NULL
    。不要使用宏,养成doi的习惯把这个给我

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

    我总是发现在做这种事情时传递双指针比通过引用传递指针更有用:

    VendingMachine::Status VendingMachine::buy(Card** card) {
        // ...
        if (NULL == *card) {
            delete *card;
            *card = NULL;
        }
    
    这迫使您在代码中对指针有点不同的处理方式,但好处是,更明显的是您在操作指针,并且消除了方法调用中的歧义:

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

    使用第二个调用,您只需查看它,该方法可以并且可能会修改<代码>卡的值。

    调用<代码>删除>代码>不会使指针为空。这需要明确地进行。您可能想考虑“销毁”。标记,而不是删除卡片对象。这将防止加载
    if NULL
    测试和需要传递指针引用。@Roddy:我认为这项作业的要点之一是教学生如何正确传递指针引用。@Justinᚅᚔᚈᚄᚒᚔ 我们得到了赋值的结构。也就是说,我们可以拥有的函数,等等。传入是赋值,我们不允许更改它。:)最好不要使用指针。传递一个
    卡片值而不是
    卡片指针
    。指针没有所有权语义,因此它是nOT清除谁负责删除它们,因此不使用(原始的那样)在现代C++中很多。当你有一个指针时,它通常被包裹在智能指针内。但是这个例子很简单,你甚至不需要指针。我会试试。非常感谢。什么是T?
    VendingMachine::Status VendingMachine::buy(Card** card) {
        // ...
        if (NULL == *card) {
            delete *card;
            *card = NULL;
        }
    
      vend.buy(card);  // Pointer reference
      vend.buy(&card); // Pointer to pointer