const 成员上的 std::construct_at 安全吗?

Joe*_*elä 2 c++ constants c++20

我有一个Obj带有 const 成员的课程i

class Obj {
    const int i;
    ...
};
Run Code Online (Sandbox Code Playgroud)

但我需要在移动构造函数中将 i 设置为 0。(因为如果i不是0,析构函数将删除东西,并且由于我移动了对象,这将导致双重释放)

Obj::i像这样在移动构造函数中进行修改是否安全?

Obj::Obj(Obj &&other) :
    i(other.i)
{
    std::destroy_at(&other.i);
    std::construct_at(&other.i, 0);
}
Run Code Online (Sandbox Code Playgroud)

根据我的理解,当std::construct_at用“透明可替换对象”替换 other.i 时,这样做是安全的。但我不完全确定这个定义的含义:

(8) 对象 o1 可以透明地被对象 o2 替换,如果:

(8.1) o2 占用的存储空间恰好覆盖了 o1 占用的存储空间,并且
(8.2) o1 和 o2 是同一类型(忽略顶级 cv 限定符),并且
(8.3) o1 不是一个完整的 const 对象,并且
(8.4) o1 和 o2 都不是潜在重叠的子对象 ([intro.object]),并且
(8.5) o1 和 o2 都是完整的对象,或者 o1 和 o2 分别是对象 p1 和 p2 的直接子对象,并且 p1 显然可以被 p2 替换。

https://eel.is/c++draft/basic#life-8

据我了解,至少8.1、8.2和8.3适用,但我不完全确定,而且我不太理解8.4和8.5。

那么我认为这应该有效(在 C++20 中)是否正确,或者这会导致未定义的行为?

Art*_*yer 5

潜在重叠的子对象是基类子对象或标有 的成员[[no_unique_address]]Obj::i并非如此 8.4 适用。

如果您将 p1 和 p2 视为同一个对象,other,则 8.5 可能适用(对象可以透明地替换自身),除非它不递归应用(例如,是某个其他类的Obj基类/成员,或者[[no_unique_address]]它所属的完整对象是const并且other曾经是const_cast或现在是可变成员)。但它实际上总是适用的。

但请考虑不将其设为const成员,因为您确实需要在此处对其进行修改。您的移动构造函数也应该清除other(例如,设置任何指针nullptr,清除任何文件句柄,将其他内容清零),这样析构函数就不会意外地重复删除内容。