在自身之上构造对象 [复制]

Constructing an object over itself [duplicate]

提问人:Dr. Gut 提问时间:5/31/2023 更新时间:5/31/2023 访问量:121

问:

在 C++ 中,您可以通过销毁然后重新创建另一个相同类型的对象来重用对象的内存吗?它会起作用还是会是 UB?thisthis

在下面的示例中,我们似乎修改了一个 const 成员变量(现场演示)。

#include <new>


class Weird {
public:
    Weird(int x) : x(x) {}

    void operator=(int newX) {
        this->~Weird();
        new(this) Weird(newX);
    }

    operator int() const {
        return x;
    }

private:
    const int x;
};


int main() {
    Weird w = 1;
    w = 2;
    return w;
}
C++ undefined-behavior placement-new

评论

1赞 πάντα ῥεῖ 5/31/2023
这难道不是应该做的吗??此外,您的示例似乎受到未跟踪的指针(内存泄漏)和副本中悬空指针的影响。std::move
1赞 Jesper Juhl 5/31/2023
查找“放置新”。
6赞 user4581301 5/31/2023
C++允许许多能力,有些人认为是...不自然的。
3赞 Yksisarvinen 5/31/2023
这是一个合理的问题,IMO,我认为没有任何理由投反对票。像这样的代码永远不会通过我的代码审查,这并不意味着关于它的问题很糟糕。
2赞 tadman 5/31/2023
@Yksisarvinen同意了。仅仅因为从代码审查的角度来看这个问题很可怕并不意味着它不好。C++有很多有趣的兔子洞。

答:

1赞 Ted Lyngmo 5/31/2023 #1

它会起作用还是会是 UB?

它将工作,并且自 C++20 以来定义了行为。在以前的版本中,不允许使用成员变量执行此操作。const

在对象的生存期结束后,在重用或释放对象占用的存储之前,可以使用任何表示对象将要或曾经所在的存储位置地址的指针,但只能以有限的方式使用。

C++20 标准 [basic.life/6]

this就是这样的指针。

如果在对象的生存期结束后,在重新使用或释放对象占用的存储之前,在原始对象占用的存储位置创建一个新对象,则指向原始对象的指针、引用原始对象的引用或原始对象的名称将自动引用新对象,并且, 一旦新对象的生存期开始,就可以用于操作新对象(如果原始对象可由新对象透明地替换)。

C++20 标准 [basic.life/8]

Weird可以透明地替换为 。Weird

评论

1赞 HolyBlackCat 5/31/2023
还有 eel.is/c++draft/basic.life#8.4,即这不适用于基类和数据成员。[[no_unique_address]]
0赞 Ted Lyngmo 5/31/2023
@HolyBlackCat 是的,有很多条件需要满足,据我所知,OPs 代码满足了所有这些条件。
0赞 Matt 5/31/2023
相关问题:如果您删除该行,这仍然合法/定义明确吗?this->~Weird();
1赞 NathanOliver 5/31/2023
@Matt 仅当析构函数是微不足道的。
1赞 Dr. Gut 5/31/2023
@TedLyngmo:你没看错。谢谢。