簡體   English   中英

是否可以重載刪除運算符以將指針設置為 null?

[英]Is it possible to overload delete operator to set the pointer to null?

我想要做的是重載我的 class 的刪除運算符,以便在刪除它后自動將指針設置為 null,這樣我就可以在成員 function 中安全地刪除它,例如:

# include <iostream>

class Buddy
{
    public:

    Buddy(void) : _hp(100) { }
    ~Buddy(void) { std::cout << "Buddy is dead!" << std::endl; }

    void operator delete(void * ptr)
    {
        ::delete (Buddy*)ptr;
        ptr = nullptr;
    }

    void getDamage(int amount)
    {
        _hp -= amount;
        if (_hp <= 0)
            delete this;
    }


    private:

    int _hp;
};

void hitBuddy(Buddy *buddy)
{
    if (!buddy)
        std::cout << "Buddy is already dead!" << std::endl;
    else
    {
        std::cout << "Hitting buddy!" << std::endl;
        buddy->getDamage(70);
    }
}

int main(void)
{
    Buddy *dude = new Buddy;

    hitBuddy(dude);
    hitBuddy(dude);
    hitBuddy(dude);
    return (0);
}

但是它沒有將指針設置為 null 並且它調用了兩次析構函數,有沒有像我想做的那樣在 class 內部設置指向 null 的指針的正確方法? (輸出)

Hitting buddy!
Hitting buddy!
Buddy is dead!
Buddy is dead!
Hitting buddy!
Buddy is dead!
Buddy is dead!
a.out(79480,0x10d3cbdc0) malloc: *** error for object 0x7fe345c05790: pointer being freed was not allocated
a.out(79480,0x10d3cbdc0) malloc: *** set a breakpoint in malloc_error_break to debug
[1]    79480 abort      ./a.out

不,不可能重載operator delete ,以便將指針設置為 null。

這是因為標准要求operator delete的第一個參數(即要刪除的指針)的類型為void* ,因此operator delete只接收指針的副本,不能修改原始參數。 它不能有類型void*& (在 C++20 中,支持“破壞刪除”,在這種情況下,參數應具有C*類型,但仍不允許引用。)

實現允許在刪除表達式之后將指針清零,作為一種幫助程序員捕獲釋放后使用錯誤的技術,但您自己無法做到這一點。

有沒有像我想做的那樣在 class 內部設置指向 null 的指針的正確方法?

不,這既不可能也沒有幫助。

這個

void operator delete(void * ptr)
    {
        ::delete (Buddy*)ptr;
        ptr = nullptr;
    }

不起作用,因為 function 按值接收ptr ,所以ptr = nullptr; 只修改本地副本。

即使有可能,如果Buddy不是由new創建的,也無濟於事。 無論如何,這將是一個糟糕的設計。

使用智能 ptr 濫用,您可能會這樣做:

class Buddy
{
    Buddy() = default;
    Buddy(const Buddy&) = delete;
    Buddy& operator=(const Buddy&) = delete;
public:

    ~Buddy() { std::cout << "Buddy is dead!" << std::endl; }

    void getDamage(int amount)
    {
        _hp -= amount;
        if (_hp <= 0)
            self.reset();
    }

    static std::weak_ptr<Buddy> make() { auto p = new Buddy; return p->self; }

private:
    int _hp = 100;
    std::shared_ptr<Buddy> self{this};
};

void hitBuddy(std::weak_ptr<Buddy> buddy_weak)
{
    auto buddy = buddy_weak.lock();

    if (!buddy) {
        std::cout << "Buddy is already dead!" << std::endl;
    } else {
        std::cout << "Hitting buddy!" << std::endl;
        buddy->getDamage(70);
    }
}

int main()
{
    std::weak_ptr<Buddy> dude = Buddy::make();

    hitBuddy(dude);
    hitBuddy(dude);
    hitBuddy(dude);
}

演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM