重载操作符删除,或如何杀死一只猫? [英] overloading operator delete, or how to kill a cat?

查看:146
本文介绍了重载操作符删除,或如何杀死一只猫?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试重载操作符删除,以便我可以返回一个简单的指针,那些不想使用智能指针,但仍然能够控制什么时候删除对象。



我定义了一个Cat类,它由几个灵魂构成,有一个重载的操作符删除,什么都不做,析构函数减少灵魂的数量(也做一些吹牛)。当灵魂达到0时,析构函数调用global :: delete,cat就会死亡。



这听起来很简单,但不能按预期工作。这里是代码:

  class Cat {
public:
Cat(string n):name ),souls(9)
{cout< Myaou ...<名称<< 出生 }

〜Cat();
void operator delete(void * p){cout< !!! operator delete called\\\
; }
void report()
{cout<名称<< 在这里,<灵魂< 灵魂花费 }

friend ostream&运算符<< (const ostream& o,const Cat& cat);
private:
void kill();
const string name;
int souls;
};

Cat ::〜Cat()
{
cout< !!! dtor called\\\
;
kill();
}

void Cat :: kill()
{
if(--souls)
cout<名称<< 仍然活着!我有<灵魂< souls left.\\\
;
else {
cout<<名称<< 正在死亡...再见世界!\\\
;
:: delete((void *)this);
}
}

ostream&运算符<< (const ostream& o,const Cat& cat)
{
return o< cat.name<< 在这里,< cat.souls< 灵魂花费
}

这里是主要的:

  int main()
{
Cat * p = new Cat(Mitzi);

for(;;)
{
char c [100];
// cout<< * p;
p-> report();
cout<< 来吧,打我!
cin>> C;
delete p;
}
}



我希望循环运行9时间,然后一些不愉快(崩溃)会发生。但是,这是输出:

  Myaou ... Mitzi出生
Mitzi在这里,9个灵魂花费
来吧,打我!c
! dtor叫
Mitzi还活着!我有8个灵魂离开。
!操作员删除称为
在这里,8个灵魂花费
来,打我!c
! dtor调用
仍然活着!我有7个灵魂离开。
***检测到的glibc *** / home / davidk / workspace / string_test / Debug / string_test:double free或corruption(fasttop):0x080cd008 ***
pre>

似乎在第一次删除后,名称成员被销毁,下一次删除导致崩溃。任何解释?我在Linux上用gcc编译,可以是编译器错误?



BTW,当我使用cout< * p而不是repotr(),它也很奇怪:它进入了一个从操作符<<()内调用构造函数的无限循环。这里发生了什么? :)



感谢!

解决方案

> delete 调用对象析构函数,之后你就没有人的地方。正如其他人指出的,你想要做的是不可能的。



当对象被构造时,你所做的也是一个不一致的行为方式



根据你的想法,重写操作符 delete



在堆栈上构建时( Cat cat(Chesire cat ); )当对象超出范围时,总是被销毁。为了解决你想要做什么,你还需要改变析构函数的bahaviour为停止破坏。这是不可能的,也是非常好的原因。



所以,如果你想要ref计数,只是实现自己的机制。毕竟,如果你没有自己完成你自己的ref count内存管理,你不能调用自己一个C ++程序员:))


I am experimenting with overloading operator delete, so that I can return a plain pointer to those who don't wish to work with smart pointers, and yet be able to control when the object is deleted.

I define a class Cat that is constructed with several souls, has an overloaded operator delete that does nothing, and destructor that decrements the number of souls (and also does some bragging). When souls reaches 0 the destructor calls the global ::delete, and the cat dies.

This sounds quite simple, but does not work as expected. Here's the code:

class Cat {
public:
    Cat(string n): name(n), souls(9)
    { cout << "Myaou... " << name << " is born\n"; }

    ~Cat();
    void operator delete(void *p) { cout << "!!! operator delete called\n"; }
    void report()
    { cout << name << "'s here, " << souls << " souls to spend\n"; }

    friend ostream& operator<< (const ostream& o, const Cat& cat);
private:
    void kill();
    const string name;
    int souls;
};

Cat::~Cat()
{
    cout << "!!! dtor called\n";
    kill();
}

void Cat::kill()
{
    if (--souls)
    	cout << name << " is still alive! I have " << souls << " souls left.\n";
    else {
    	cout << name << " is dying... good bye world!\n";
    	::delete((void*)this);
    }
}

ostream& operator<< (const ostream& o, const Cat& cat)
{
    return o << cat.name << "'s here, " << cat.souls << " souls to spend\n";
}

here's the main:

int main()
{
    Cat *p = new Cat("Mitzi");

    for (;;)
    {
    	char c[100];
//  	cout << *p;
    	p->report();
    	cout << "come on, hit me!";
    	cin >> c;
    	delete p;
    }
}

I'd expect that the loop would run for 9 times, and then something unpleasant (crash) would happen. However, this is the output:

Myaou... Mitzi is born
Mitzi's here, 9 souls to spend
come on, hit me!c
!!! dtor called
Mitzi is still alive! I have 8 souls left.
!!! operator delete called
's here, 8 souls to spend
come on, hit me!c
!!! dtor called
 is still alive! I have 7 souls left.
*** glibc detected *** /home/davidk/workspace/string_test/Debug/string_test: double free or corruption (fasttop): 0x080cd008 ***

Seems that after the first delete the name member is destroyed, and the next delete causes a crash. Any explanations? I am compiling with gcc on Linux, can be a compiler bug?

BTW, when I used the operator<<() as in cout << *p instead of repotr(), it was also weird: it entered an infinite loop of calling the constructor from within the operator<<(). What's going on here? :)

thanks!

解决方案

operator delete calls the object destructor and after that you are in no man's land. As others pointed out, what you are trying to do is not possible.

What you are doing is also a bit dodgy in the way of inconsistent behaviour when the object is constructed on the heap and on the stack.

With your idea to override operator delete the object will stay alive depending on some internal logic (the number of lives has reached 9) if constructed using new.

When constructed on the stack (Cat cat("Chesire cat");) the object will always get destructed when it goes out of scope. In order to achive what you are trying to do you will also need to change the bahaviour of the destructor to "stop destructing". This is not possible, also for very good reasons.

So, if you want ref counting, just implement your own mechanism. After all, you can't call yourself a C++ programmer if you haven't done your own ref count memory management at least once :))

这篇关于重载操作符删除,或如何杀死一只猫?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆