[Это продолжение после can memcpy() be used to change “const” member data?. И Idiomatic Way to declare C++ Immutable Classes действительно попадает в проблему, особенно this ответ «На языке, разработанном вокруг неизменяемых данных, он знал бы, что он может« перемещать »ваши данные, несмотря на свою (логическую) неизменность». ]может быть использовано «новое» для изменения данных «const»?
дан struct
с const
членами
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
см:
Bar bar; // (0, 0)
bar.move_x(3141); // (3141, 0)
Оба point2d
и Bar
работают точно по желанию; да, point2d
абсолютно неизменен.
Тем не менее, мне бы очень понравилась другая реализация Bar
, которая хранит экземпляр point2d
в качестве данных элемента. Есть ли способ достичь этого? Использование места размещения new
предположительно приводит к undefined behavior (см. Комментарий).
#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 };
}
};
ли не с использованием 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
? Или Baz
также хорошо? Или нет, и единственным решением является Bar
?
Почему вы говорите, что размещение новых результатов в UB, когда «доказательство», с которым вы связаны, не имеет ничего общего с размещением нового? Что мне не хватает? –
@ Светлый комментарий в связанном ответе говорит, что размещение 'new' совпадает с' memcpy() ' –
О, комментарии, бла. Не уверен, что я согласен с Сэмом. Размещение нового as-if разрушает оригинал (который четко определен, если он тривиально разрушен, например, 'int') и заменяет его чем-то новым. Имейте в виду, что «объект» - это область памяти.Но у него также есть тип. Эти два варианта не подходят для размещения новых. Я думаю, что вопрос о том, будет ли это быть UB, будет довольно интересным. Сначала я задал этот вопрос. –