首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >对于琐碎的对象来说,用“`this`”来称呼新的位置安全吗?

对于琐碎的对象来说,用“`this`”来称呼新的位置安全吗?
EN

Stack Overflow用户
提问于 2019-10-29 12:39:05
回答 2查看 973关注 0票数 20

我知道这个问题已经问过好几次了,但我还是找不到这个问题的答案。

假设我有一个琐碎的类,它不拥有任何资源,并且具有空析构函数和默认构造函数。它有少量的类内初始化的成员变量,其中没有一个是const

我想重新初始化此类类的对象,而不需要手工编写deInit方法。这样做安全吗?

代码语言:javascript
运行
复制
void A::deInit()
{
  new (this)A{};
}

我看不出它有什么问题--对象总是处于有效状态,this仍然指向同一个地址;但是它是C++,所以我想确认一下。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-29 12:50:40

类似于delete this的合法性,据我所知,this的新位置也是允许的。另外,关于this或其他预先存在的指针/引用之后是否可以使用的问题,有几个限制:

basic.life 如果在对象的生存期结束后,在对象占用的存储被重用或释放之前,在原始对象占用的存储位置创建一个新对象,指向原始对象的指针,引用原始对象的引用,或原始对象的名称,则可以自动引用新对象,并且一旦新对象的生存期启动,就可以使用它来操作新对象,如果:

  • 新对象的存储完全覆盖原始对象占用的存储位置,以及
  • 新对象与原始对象的类型相同(忽略顶级cv-限定符),以及
  • 原始对象的类型不是const限定的,如果是类类型,则不包含任何类型为const限定或引用类型的非静态数据成员,以及
  • 原始对象和新对象都不是潜在的重叠子对象(intro.object)。

在这个例子中,前两个是满意的,但是需要考虑最后两个。

关于第三点,考虑到函数是非const限定的,假定原始对象是非const应该是相当安全的。如果恒常已被抛弃,故障就在主叫方。关于const / reference成员,我认为可以通过断言这是可分配的:

代码语言:javascript
运行
复制
static_assert(std::is_trivial_v<A> && std::is_copy_assignable_v<A>);

当然,由于可分配性是一个要求,所以您可以使用*this = {};,我希望它能生成相同的程序。一个可能更有趣的用例可能是将*this的内存重用到另一种类型的对象(这将满足使用this的要求,至少不需要重新解释+清洗)。

delete this类似,this的新位置很难被描述为“安全”。

票数 17
EN

Stack Overflow用户

发布于 2019-10-29 12:53:19

涵盖此问题的规则在[basic.life]/5中。

程序可以通过重用对象占用的存储或显式调用类类型的对象的析构函数来结束任何对象的生存期。对于类类型的对象,在对象占用的存储被重用或释放之前,程序不需要显式调用析构函数;但是,如果没有对析构函数的显式调用,或者如果未使用删除表达式释放存储,则不会隐式调用析构函数,并且任何依赖于析构函数产生的副作用的程序都具有未定义的行为。

[basic.life]/8

如果在对象的生存期结束后,在对象占用的存储被重用或释放之前,在原始对象占用的存储位置创建一个新对象,指向原始对象的指针,引用原始对象的引用,或原始对象的名称,则可以自动引用新对象,并且一旦新对象的生存期启动,就可以使用它来操作新对象,如果:

  • 新对象的存储完全覆盖原始对象占用的存储位置,以及
  • 新对象与原始对象的类型相同(忽略顶级cv-限定符),以及
  • 原始对象的类型不是const限定的,如果是类类型,则不包含任何类型为const限定或引用类型的非静态数据成员,以及
  • 原始对象和新对象都不是潜在的重叠子对象(intro.object)。

因为您的对象是琐碎的,所以您不必担心basic.life/5,只要您满足basic.life/8中的要点,那么它是安全的。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58607661

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档