简体   繁体   English

试图理解 int main c++ 中删除对象的行为

[英]Trying to understand The behaviour of delete object in int main c++

If I remove either one of the line delete Jim;如果我删除其中任何一行,请delete Jim; or delete DiamondWeapon;delete DiamondWeapon; it works, but Why?它有效,但为什么? What I meant here is, If I just use delete DiamondWeapon;我的意思是,如果我只是使用delete DiamondWeapon; it will work but If I also just use delete Jim;它会工作,但如果我也只使用delete Jim; and I remove delete DiamondWeapon;然后我删除delete DiamondWeapon; it will work too.它也会起作用。 I am having hard time wrapping my head around it any help will really be appreciated我很难将头环绕在它周围,任何帮助都将不胜感激

#include<iostream>
#include<string>

// Strategy pattern IBehaviour (Iweapon)
// Context Character ( will access this.strategy_.Function() ) ( his.strategy will be Iweapon )
// Concrete Strategies ( Each weapon will have a unique Algorithms for each weapon ).


class Iweapon // ( interface Ibehaviour strategy )
{
public:
    virtual ~Iweapon() { }
    virtual void Use() const = 0; /* Search Results Featured snippet from the web
                                    The const member functions are the functions which are declared as constant in the program.
                                    The object called by these functions cannot be modified.It is recommended
                                    to use const keyword so that accidental changes to object are avoided.A const member function can be called by any type of object.*/
};

class Character // its Context as per UML diagram
{
private:
    Iweapon* iweapon_Strat;
public:
    Character(Iweapon* iweaponStrat = nullptr) :iweapon_Strat(iweaponStrat) { }
    /*{
        this->iweapon_Strat = iweaponStrat;
    }*/
    ~Character() {
        delete  this->iweapon_Strat;
    }

    void SetStrategy(Iweapon* iweaponstrat) {
        delete this->iweapon_Strat;
        this->iweapon_Strat = iweaponstrat;
    }

    void Attack() const //DoSomeLogic() 
    {
        this->iweapon_Strat->Use();
    }
};

// following are ConcreteStrategies(A,B,C ... ) 

class Sword :public Iweapon {
public:
    void Use() const override {
        std::cout << "\n\nSword is Attacking\n\n";
    }
};

class Axe : public Iweapon {
public:
    void Use() const override {
        std::cout << "\n\nAxe is Attacking\n\n";
    }
};

int main() {
    //this work
    {
        Character* Mike = new Character(new Sword);
        Mike->Attack();
        Mike = new Character(new Axe);
        Mike->Attack();

        delete Mike;
    }
    //this work too
    {

        Character* Ryan = new Character();
        Iweapon* SilverWeapon = NULL;

        SilverWeapon = new Sword;
        Ryan->SetStrategy(SilverWeapon);
        Ryan->Attack();

        SilverWeapon = new Axe;
        Ryan->SetStrategy(SilverWeapon);
        Ryan->Attack();

        delete Ryan;
    }
    //this doesn't work but if I remove either one of the line *** delete Jim; *** or *** delete DiamondWeapon; *** it work, But Why
    // i meant here is : Alone if I just have delete DiamondWeapon; it will work
    // but if Alone i also just have delete Jim; and I remove delete DiamondWeapon; it will work too.
    //I am having hard time wraping my head around it any help will really be appreciated
    {
        Iweapon* DiamondWeapon = new Sword();
        Character* Jim = new Character();

        DiamondWeapon = new Sword();
        Jim->SetStrategy(DiamondWeapon);
        Jim->Attack();

        DiamondWeapon = new Axe();
        Jim->SetStrategy(DiamondWeapon);
        Jim->Attack();

        delete DiamondWeapon;
        delete Jim;
    }
    //This also doesn't work
    {
        Iweapon* WoodenWepon = new Sword();
        Character Kim;

        //WoodenWepon = new Sword();
        Kim.SetStrategy(WoodenWepon);
        Kim.Attack();

        WoodenWepon = new Axe();
        Kim.SetStrategy(WoodenWepon);
        Kim.Attack();

        delete WoodenWepon;
        //delete Kim;
    }
    //this Work
    {
        Character* Denzel = new Character();
        Iweapon* weapon = new Sword;
        Denzel->SetStrategy(weapon);
        Denzel->Attack();

        Denzel->SetStrategy(new Axe);
        Denzel->Attack();

        //delete weapon;
        delete Denzel;
    }
    // This also work
    {
        Iweapon* GoldWeapon = NULL;
        Character* Jhon = new Character();

        GoldWeapon = new Sword;
        Jhon->SetStrategy(GoldWeapon);
        Jhon->Attack();

        GoldWeapon = new Axe;
        Jhon->SetStrategy(GoldWeapon);
        Jhon->Attack();

        delete GoldWeapon;
        //delete Jhon;
    }


    //following is just for system pause
    std::string end;
    std::cin >> end;
    return 0;
}

When you do:当你这样做时:

void Character::SetStrategy(Iweapon* iweaponstrat) 
{
    delete this->iweapon_Strat;
    this->iweapon_Strat = iweaponstrat;
}

Character takes ownership of the pointer.字符拥有指针的所有权。 Your code will handle deletion of the iweaponstrat .您的代码将处理iweaponstrat删除。 It's not clear if it's by design or accident, but since the delete is there, we can say that it dos act as an owner.目前还不清楚是有意还是无意,但既然delete在那里,我们可以说它确实充当了所有者。

Now, when you do:现在,当你这样做时:

DiamondWeapon = new Axe();
Jim->SetStrategy(DiamondWeapon); // allows deletes DiamondWeapon
Jim->Attack();

delete DiamondWeapon; // deletes DiamondWeapon

You give an Axe to Jim, giving him ownership and you also delete it yourself.你给了吉姆一把Axe ,给了他所有权,你也自己删除了它。 This is asking for trouble, which eventually occurs.这是自找麻烦,最终会发生。

You have two paths from here:从这里你有两条路径:

  • Use shared_ptr or unique_ptr , strongly recommended.强烈推荐使用shared_ptrunique_ptr
  • Define clear ownership, respect it, and only delete owned objects.定义明确的所有权,尊重它,并且只删除拥有的对象。 Very tough to pull off.非常难以拉断。 C programmers have to deal with this all the time, it saves the overhead of smart pointers, but really not worth the effort at your level. C程序员必须一直处理这个问题,它节省了智能指针的开销,但在你的水平上真的不值得付出努力。

The problem you have is multiple copies of the same pointer value.您遇到的问题是同一指针值的多个副本。

When you当你

delete DiamondWeapon;
delete Jim; 

The destructor ~Character tries to delete the object that DiamondWeapon also pointed to.析构函数~Character试图删除DiamondWeapon也指向的对象。 This is incorrect C++, and your program's behaviour is undefined.这是不正确的 C++,并且您的程序的行为未定义。

Rather than passing around raw ( * ) pointers, you should use std::unique_ptr , so that you know there is only ever one pointer pointing to each Weapon and Character您应该使用std::unique_ptr ,而不是传递原始 ( * ) 指针,以便您知道只有一个指针指向每个WeaponCharacter

class Character // its Context as per UML diagram
{
private:
    std::unique_ptr<Iweapon> iweapon_Strat;
public:
    Character(std::unique_ptr<Iweapon> iweaponStrat) :iweapon_Strat(iweaponStrat) {}

    void SetStrategy(std::unique_ptr<Iweapon> iweaponstrat) 
    {
        iweapon_Strat = iweaponstrat;
    }

    void Attack() const
    {
        iweapon_Strat->Use();
    }
};

Then you will have a compile time error when you hold extra pointers.那么当您持有额外的指针时,您将遇到编译时错误。 As a bonus, your dynamic-storage-duration ("Heap") objects are cleaned up when the scope defining the pointer ends.作为奖励,当定义指针的范围结束时,您的动态存储持续时间(“堆”)对象将被清除。

int main() 
{
    //this work
    {
        auto Mike = std::make_unique<Character>(std::make_unique<Sword>());
        Mike->Attack();
        Mike = std::make_unique<Character>(std::make_unique<Axe>());
        Mike->Attack();
    }
    //this work too
    {
        
        auto Ryan = std::make_unique<Character>Character();
        std::unique_ptr<Iweapon> SilverWeapon;
    
        SilverWeapon = std::make_unique<Sword>();
        // Ryan->SetStrategy(SilverWeapon); // Error, can't copy SilverWeapon
        Ryan->SetStrategy(std::move(SilverWeapon)); // SilverWeapon is now null
        Ryan->Attack();
    
        SilverWeapon = std::make_unique<Axe>();
        // Ryan->SetStrategy(SilverWeapon); // Error, can't copy SilverWeapon
        Ryan->SetStrategy(std::move(SilverWeapon)); // SilverWeapon is now null
        Ryan->Attack();
    }
    {
        std::unique_ptr<Iweapon> DiamondWeapon = std::make_unique<Sword>();
        auto Jim = std::make_unique<Character>Character();
    
        DiamondWeapon = std::make_unique<Sword>();
        // Jim->SetStrategy(DiamondWeapon); // Error, can't copy DiamondWeapon
        Jim->SetStrategy(std::move(DiamondWeapon)); // DiamondWeapon is now null
        Jim->Attack();
    
        DiamondWeapon = std::make_unique<Axe>();
        // Jim->SetStrategy(DiamondWeapon); // Error, can't copy DiamondWeapon
        Jim->SetStrategy(std::move(DiamondWeapon)); // DiamondWeapon is now null
        Jim->Attack();
    }
    {
        std::unique_ptr<Iweapon> WoodenWepon = std::make_unique<Sword>();
        Character Kim;
    
        // Kim.SetStrategy(WoodenWepon); // Error, can't copy WoodenWeapon
        Kim.SetStrategy(std::move(WoodenWepon)); // WoodenWeapon is now null
        Kim.Attack();
    
        WoodenWepon = std::make_unique<Axe>();
        // Kim.SetStrategy(WoodenWepon); // Error, can't copy WoodenWeapon
        Kim.SetStrategy(std::move(WoodenWepon)); // WoodenWeapon is now null
        Kim.Attack();
    }
    // etc.        
    
    //following is just for system pause
    std::string end;
    std::cin >> end;
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM