[ 这是后续memcpy() 可以用来更改“const”成员数据吗?. And 声明 C++ 不可变类的惯用方式真正解决这个问题,尤其是this回答“在围绕不可变数据设计的语言中,它知道它可以“移动”您的数据,尽管它具有(逻辑)不变性。” ]
Given a struct
with const
members
struct point2d { const int x; const int y; }; // can't change to remove "const"
一个类,它持有一个指向point2d
可以指向一个新的point2d
具有不同值的实例。
struct Bar
{
std::unique_ptr<point2d> pPt_{ new point2d{ 0, 0 } };
const point2d& pt() const {
return *pPt_;
}
void move_x(int value) {
pPt_.reset(new point2d{ pt().x + value, pt().y });
}
};
的客户Bar
see:
Bar bar; // (0, 0)
bar.move_x(3141); // (3141, 0)
Both point2d
and Bar
完全按照预期工作;是的,point2d
是完全不可变的。
但是,我真的想要一个不同的实现Bar
存储的point2d
实例作为成员数据。有什么办法可以实现这一点吗?使用放置new
据说结果是未定义的行为(见评论)。
#include <new>
struct Baz
{
point2d pt{ 0, 0 };
void move_x(int value) {
// ** is this undefined behavior ? **
new (&pt) point2d { pt.x + value, pt.y };
}
};
Does not using point2d
直接作为成员数据解决(潜在?)未定义的行为?
struct Blarf
{
unsigned char pt_[sizeof(point2d)];
const point2d& pt() const {
return *reinterpret_cast<const point2d*>(pt_);
}
Blarf() {
new (&pt_) point2d{ 0, 0 };
}
void move_x(int value) {
new (&pt_) point2d{ pt().x + value, pt().y };
}
};
哪个是对的?只是Blarf
? Or is Baz
还可以吗?或者两者都不是,唯一的解决方案是Bar
?