Яка мета std :: прання?


242

P0137 вводить шаблон функції std::launderта вносить багато, багато змін до стандарту в розділи, що стосуються об'єднань, часу життя та покажчиків.

Яку проблему вирішує цей документ? Які зміни в мові я повинен знати? А що ми з launderвами?


2
Ви питаєте про саму папір чи про неї std::launder? std::launderвикористовується для "отримання вказівника на об'єкт, створений у сховищі, зайнятому існуючим об'єктом одного типу, навіть якщо він має const або посилання членів".
txtechhelp

7
корисне посилання на тему. Також це питання stackoverflow.com/questions/27003727/…
Пол Руні

Тепер це було випущено у VC2017 у версії 15.7.0
Даміан

За словами std, покажчики - тривіальні типи, тому прання нічого не робить. ;)
допитливий хлопець

Відповіді:


250

std::launderвлучно названо, хоча тільки якщо ви знаєте, для чого це. Він виконує відмивання пам'яті .

Розглянемо приклад у статті:

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

U u = {{ 1 }};

Ця заява виконує агрегування ініціалізації, ініціалізацію першого члена Uз {1}.

Оскільки nце constзмінна, компілятор може вільно вважати, що завждиu.x.n має бути 1.

Що ж станеться, якщо ми це зробимо:

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

Оскільки Xтривіально, нам не потрібно руйнувати старий об’єкт перед тим, як створити на його місці новий, тому це ідеально юридичний код. У нового об’єкта його nучасник буде 2.

Тож скажи мені ... що u.x.nповернеться?

Очевидною відповіддю буде 2. Але це неправильно, оскільки компілятору дозволено припустити, що справді constзмінна (не просто a const&, а оголошена змінна об'єкт const) ніколи не зміниться . Але ми просто змінили це.

[basic.life] / 8 викладає обставини, коли для доступу до новоствореного об’єкта є нормальним за допомогою змінних / покажчиків / посилань на старий. А наявність constчлена - один із факторів, що дискваліфікують.

Отже ... як можна u.x.nправильно говорити ?

Ми повинні відмити пам’ять:

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

Відмивання грошей використовується для запобігання пошуку людей, звідки ви отримали свої гроші. Відмивання пам'яті використовується для запобігання компілятору відстежувати, звідки ви отримали ваш об'єкт, таким чином змушуючи його уникати будь-яких оптимізацій, які більше не застосовуються.

Ще один із факторів дискваліфікації - це якщо ви змінюєте тип об'єкта. std::launderможе допомогти і тут:

aligned_storage<sizeof(int), alignof(int)>::type data;
new(&data) int;
int *p = std::launder(reinterpret_cast<int*>(&data));

[basic.life] / 8 повідомляє нам, що якщо ви виділите новий об’єкт у сховищі старого, ви не можете отримати доступ до нового об’єкта через покажчики на старий. launderдозволяє нам у бік цього кроку.


34
Так мій tl; dr правильний: "відмивання - це в основному покарання, яке не є членом UB"?
druckermanly

13
Чи можете ви пояснити, чому це правда? "Оскільки nце constзмінна, компілятор вільний припустити, що u.x.nзавжди має бути 1." Де в стандарті це написано? Я прошу, бо сама проблема, на яку ви вказали, могла б означати, що вона в першу чергу помилкова. Це має бути істинним лише за правилом нібито, яке тут не вдається. Що я пропускаю?
користувач541686

10
@Mehrdad [basic.life] / 8: " Якщо, [...] буде створено новий об'єкт у місці зберігання, який займав початковий об'єкт [...] ім'я оригінального об'єкта автоматично посилається на новий об'єкт [...] якщо: [...] тип [...] не містить жодного нестатичного члена даних, тип якого має кваліфікацію const або тип посилання [...] "
ecatmur

14
@Barry Дуже; якщо немає об’єктів типу T, розташованих за адресою, що ptrпредставляє, ви порушите launderпередумову, тому немає сенсу говорити про результат.
ТК

17
@ NicolBolas Можна лише сподіватися, що supercat робить стільки ж лобіювання Комітетів, скільки вони нескінченно вимагають відповідей від інших користувачів сторонніх мов. Крім того, хороший оптимізуючий компілятор все одно оптимізує ваше правильне рішення внутрішньої memcpyреінтерпретації на підтримуваних платформах (тобто в'яже вирівнювання) .
підкреслити_12
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.