Что Стандарт может сказать о приведенном ниже коде?
#include <iostream>
#include <chrono>
#include <thread>
int main()
{
static_assert(sizeof(int) == sizeof(float));
using namespace std::chrono_literals;
auto pi = new int{10};
std::thread t([pi]() {
for (int i = 0; i < 3; i++) {
std::cout << *pi << '\n';
std::this_thread::sleep_for(1s);
}
});
std::this_thread::sleep_for(1s);
auto pf = ::new (pi) float{};
*pf = -1.0;
t.join();
}
Мне особенно любопытно, как (или возможно) применить [basi c .life] / 7 и [basi c .life] / 8 , говоря
Аналогично, до начала срока службы объекта, но после хранилища, которое объект будет занимать был выделен или, после истек срок жизни объекта и до повторного использования или освобождения памяти, занятой объектом
и
Если после истек срок жизни объекта и до повторного использования или освобождения хранилища, которое занимал объект, в месте хранения, которое занимал исходный объект
*, создается новый объект 1023 * соответственно, учитывая, что
[basi c .life] / 11 говорит
В этом разделе «до» и «после» относятся к «* 1029». * происходит до ”отношения.
Означает ли это, что если поток делает не "видит" конец времени жизни int
объекта, он может получить к нему доступ, как если бы он был жив?
Сначала я подумал, что программа имеет гонку данных :
Выполнение программы содержит гонку данных , если она содержит два потенциально одновременных конфликтующих действия, по крайней мере одно из которых не атоми c, и ни одно не происходит раньше другого, за исключением специального случая для обработчиков сигналов, описанных ниже. Любая такая гонка данных приводит к неопределенному поведению.
Однако конфликтующих действий нет. По определению "конфликта" :
Две оценки выражений конфликт , если одна из них изменяет область памяти , а другая каждый читает или изменяет ту же самую ячейку памяти.
и определение "ячейки памяти" :
A ячейка памяти является либо объектом скалярного типа, либо максимальной последовательностью смежных битовых полей, все из которых имеют ненулевую ширину.
считывает *pi
не конфликтует с хранилищем через *pf
, потому что эти значения l обозначают разные объекты и, следовательно, разные ячейки памяти.
Мне кажется, что в программе должен быть UB, но я не вижу, где.