Какова цель СТД::отмывать?

Р0137 вводит шаблон функции `СТД::отмыть и многие, многие изменения в разделы, касающиеся профсоюзов, жизни, и указатели.

В чем проблема этого документа-решения? Какие изменения в языке, что я должен быть в курсе? И что нам отмывать передоза?

Комментарии к вопросу (4)
Решение

СТД::отмыть-это метко назвал, но только если вы знаете, что это's для. Он выполняет отмывание памяти.

Рассмотрим пример, приведенный в статье:

struct X { const int n; };
union U { X x; float f; };
...

U u = {{ 1 }};

Это заявление выполняет агрегатной инициализации, инициализации первым членом У с {1}.

Потому что N - это константный переменная, компилятор волен считать, что `у.х.н-будет всегда быть 1.

Так что' случается, если мы делаем это:

X *p = new (&u.x) X {2};

Потому что " X " - это тривиально, мы не должны уничтожить старый объект перед созданием нового на его место, так что это абсолютно легальный код. Новый объект будет иметь свою Н члены 2.

Так скажи мне... что у.х.Н-возвращение?

Очевидный ответ будет 2. Но, что'ы не так, потому что компилятор это позволило предположить, что по-настоящему константной переменной (не простокак const&, но объект переменной *заявил*как const`) ничего не меняется. Но мы просто поменяли его.

[основные.жизнь]/8 изложены обстоятельства, когда это ОК, чтобы открыть вновь созданный объект через переменные/указателей/ссылок на старый. И имея `константный член-одна из дисквалифицирующие факторы.

Так что... как мы можем говорить о `у.х.Н-правильно?

Мы должны отмывать нашей памяти:

assert(*std::launder(&u.x.n) == 2); //Will be true.

Отмывание денег используется для предотвращения людей от трассировки, где вы получили свои деньги от. Отмывание память используется для предотвращения компилятор от розыска, где у тебя объект, тем самым заставляя его, чтобы избежать каких-либо оптимизаций, которые больше не могут применяться.

Другой дисквалифицирующий факторов при изменении типа объекта. СТД::отмыть также может помочь здесь:

aligned_storage::type data;
new(&data) int;
int *p = std::launder(reinterpret_cast(&data));

[основные.жизнь]/8 говорит нам, что если вы выделить новый объект в хранилище старый, вы не можете открыть новый объект через указатели на старый. "химичить" позволяет обойти это.

Комментарии (47)