当我在写一个字符串类的演示时,在复制赋值函数中,我试图在复制前通过“删除这个”来清除自己,但是失败了。
Str &operator=(const Str &s) {
if (this != &s) { // self-assignment check
//delete this; //cannot run as I imagine
this->~Str();
_size = s._size;
_str = new char[_size + 1];
memcpy(_str, s._str, _size + 1);
}
return *this;
}
~Str() {
_size = 0;
delete[] _str;
}
Linux告诉我
双重释放或损坏(输出)已中止(核心转储)
2条答案
按热度按时间yqlxgs2m1#
delete x;
等效于x->~T();
后跟operator delete(x)
(类似于free(x)
,但可能不兼容)。x->~T();
是一个危险的工具,在这种情况下它必须跟在new(this) T(...);
(placement-new)后面才能调用构造函数,否则当前对象被认为是“死的”,与它的任何交互都会导致未定义的行为。但是即使你调用placement-new,它也会抛出,然后对象保持死状态,当调用者试图再次销毁已经死了的对象时,调用者会得到UB。
结论:
x->~T();
很难正确使用,使用其他东西。这是写赋值语句的一种通用方法。它既可以用作复制赋值语句,也可以用作移动赋值语句,而且是异常安全的,等等。
plupiseo2#
你的
delete this
已经执行了this->~Str()
,但这只是一个问题。在delete this
之后,你调用了_size = s._size
,它实际上是this->_size = s._size
。但是this
的生存期已经结束,所以任何对this
的调用都可能导致未定义的行为。所以delete this
和this->~Str()
都不属于你的赋值运算符。