我知道这个问题已经问过好几次了,但我还是找不到这个问题的答案。
假设我有一个琐碎的类,它不拥有任何资源,并且具有空析构函数和默认构造函数。它有少量的类内初始化的成员变量,其中没有一个是const。
我想重新初始化此类类的对象,而不需要手工编写deInit方法。这样做安全吗?
void A::deInit()
{
new (this)A{};
}我看不出它有什么问题--对象总是处于有效状态,this仍然指向同一个地址;但是它是C++,所以我想确认一下。
发布于 2019-10-29 12:50:40
类似于delete this的合法性,据我所知,this的新位置也是允许的。另外,关于this或其他预先存在的指针/引用之后是否可以使用的问题,有几个限制:
basic.life 如果在对象的生存期结束后,在对象占用的存储被重用或释放之前,在原始对象占用的存储位置创建一个新对象,指向原始对象的指针,引用原始对象的引用,或原始对象的名称,则可以自动引用新对象,并且一旦新对象的生存期启动,就可以使用它来操作新对象,如果:
在这个例子中,前两个是满意的,但是需要考虑最后两个。
关于第三点,考虑到函数是非const限定的,假定原始对象是非const应该是相当安全的。如果恒常已被抛弃,故障就在主叫方。关于const / reference成员,我认为可以通过断言这是可分配的:
static_assert(std::is_trivial_v<A> && std::is_copy_assignable_v<A>);当然,由于可分配性是一个要求,所以您可以使用*this = {};,我希望它能生成相同的程序。一个可能更有趣的用例可能是将*this的内存重用到另一种类型的对象(这将满足使用this的要求,至少不需要重新解释+清洗)。
与delete this类似,this的新位置很难被描述为“安全”。
发布于 2019-10-29 12:53:19
涵盖此问题的规则在[basic.life]/5中。
程序可以通过重用对象占用的存储或显式调用类类型的对象的析构函数来结束任何对象的生存期。对于类类型的对象,在对象占用的存储被重用或释放之前,程序不需要显式调用析构函数;但是,如果没有对析构函数的显式调用,或者如果未使用删除表达式释放存储,则不会隐式调用析构函数,并且任何依赖于析构函数产生的副作用的程序都具有未定义的行为。
如果在对象的生存期结束后,在对象占用的存储被重用或释放之前,在原始对象占用的存储位置创建一个新对象,指向原始对象的指针,引用原始对象的引用,或原始对象的名称,则可以自动引用新对象,并且一旦新对象的生存期启动,就可以使用它来操作新对象,如果:
因为您的对象是琐碎的,所以您不必担心basic.life/5,只要您满足basic.life/8中的要点,那么它是安全的。
https://stackoverflow.com/questions/58607661
复制相似问题