【问题标题】:Is it valid to call destructor on 'this' and then assign a new value to 'this'?在'this'上调用析构函数然后为'this'分配一个新值是否有效?
【发布时间】:2021-09-13 18:25:57
【问题描述】:

假设我正在实现某个类A,它有一个clear() 方法,应该将对象状态设置为“全新”状态,就好像它刚刚使用构造函数创建一样:

  • 我应该释放当前对象正在使用的所有资源(与 A::~A() 完全相同),
  • 然后我应该再次初始化这些资源(与A::A() 完全相同)。

所以我最初的想法是这样的:

void A::clear() {
  this->~A();
  *this = A();
}

但是,我被告知此代码会导致 UB,因为在调用其析构函数后我无法取消引用 this。但同时我也被告知了一个更好的主意:如果我们使用placement new,就没有解除引用,所以这实际上可能有效:

void A::clear() {
  this->~A();
  new (this) A();
}

这让人感觉非常不舒服,而且很容易出错……那么这段代码真的有效吗?

【问题讨论】:

  • 你的析构函数应该调用一个 clear() 函数来执行“清除”,而不是相反。此外,如果用户真的真的想将他们的对象设置为全新的、干净的状态,那么让他们明确地这样做,即A myA;...myA = {};——无需手持。
  • 1.如果构造函数抛出,会发生什么? 2. 你就不能*this = A();吗?
  • @prapin 嗯? OP 分配给*this 而不是this,这一直是合法的(或者如果他们不调用析构函数,也是合法的)。
  • 相关/欺骗:stackoverflow.com/questions/1124634/…。它没有提到this,但是指向对象的指针就是指向对象的指针,所以应该是同一个答案。
  • 不幸的是,这是合法的。 C++ 标准中有一个例子就是这样做的。但是如果有人创建了一个派生自这个类的类会发生什么?现在,如果析构函数工作正常(即它是虚拟的,或者它们只是不走运),则代码已将派生类型的对象转换为基类型的对象。

标签: c++ destructor object-lifetime sanity-check


【解决方案1】:

这段代码真的有效吗?

您的代码有效。仅仅更改对象的值也是一种相当不寻常的方法。

如果实现正确,单独的赋值运算符将实现这一点。

void A::clear() {
  *this = A();
}

如果此代码未按预期工作,则您的赋值运算符未正确实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    • 1970-01-01
    • 2016-10-12
    • 1970-01-01
    相关资源
    最近更新 更多