交换 const 成员是未定义的行为吗? C++17
Is swapping a const member undefined behavior? C++17
https://godbolt.org/z/E3ETx8a88
这是换UB吗?我在改变什么吗? UBSAN 没有报告任何东西。
#include <utility>
struct MyInt
{
MyInt(int ii): i(ii) {}
const int i;
MyInt& operator=(MyInt&& rh)
{
std::swap(const_cast<int&>(i), const_cast<int&>(rh.i));
return *this;
}
};
int main() {
MyInt i0(0);
MyInt i2(2);
i0 = std::move(i2);
return i0.i;
}
Is this swapping UB?
是的,这是UB。
Am I mutating anything?
您正在改变 const 对象。这是不允许的。
Modifying a const object through a non-const access path and referring to a volatile object through a non-volatile glvalue results in undefined behavior.
所以对,就是UB
这似乎是 c++ 进化的一个领域。
由于this restriction on replacing const member objects
,它在 c++17 中是 UB
但是,在以后的版本中,this restriction is mostly removed.。对完整的 const 对象仍然存在限制。例如,如果 MyInt i0(0);
是 const MyInt i0(0);
,则不能这样做
尽管 c++20 现在允许修改 const 子对象,但最好避免 const_cast
并使用它来创建赋值构造函数。在这种情况下,不需要析构函数,因为它很容易被破坏。请注意,在 c++20 之前必须使用 placement new 并且仍然是 UB,因为以前不允许更改 const 子对象。
constexpr MyInt& operator=(MyInt&& rh)
{
std::construct_at(&this->i, rh.i);
return *this;
}
https://godbolt.org/z/E3ETx8a88
这是换UB吗?我在改变什么吗? UBSAN 没有报告任何东西。
#include <utility>
struct MyInt
{
MyInt(int ii): i(ii) {}
const int i;
MyInt& operator=(MyInt&& rh)
{
std::swap(const_cast<int&>(i), const_cast<int&>(rh.i));
return *this;
}
};
int main() {
MyInt i0(0);
MyInt i2(2);
i0 = std::move(i2);
return i0.i;
}
Is this swapping UB?
是的,这是UB。
Am I mutating anything?
您正在改变 const 对象。这是不允许的。
Modifying a const object through a non-const access path and referring to a volatile object through a non-volatile glvalue results in undefined behavior.
所以对,就是UB
这似乎是 c++ 进化的一个领域。
由于this restriction on replacing const member objects
,它在 c++17 中是 UB但是,在以后的版本中,this restriction is mostly removed.。对完整的 const 对象仍然存在限制。例如,如果 MyInt i0(0);
是 const MyInt i0(0);
尽管 c++20 现在允许修改 const 子对象,但最好避免 const_cast
并使用它来创建赋值构造函数。在这种情况下,不需要析构函数,因为它很容易被破坏。请注意,在 c++20 之前必须使用 placement new 并且仍然是 UB,因为以前不允许更改 const 子对象。
constexpr MyInt& operator=(MyInt&& rh)
{
std::construct_at(&this->i, rh.i);
return *this;
}