Но у меня есть вопрос, который пришел мне в голову при ответе на вышеизложенное: можно проиллюстрировать этим фрагментом:
Код: Выделить всё
#include
#include
#include
#include
struct S {
alignas(std::uint64_t) alignas(std::uint32_t)
std::array storage = {some init values};
};
int main()
{
S s;
std::uint64_t* pi64 = std::start_lifetime_as(s.storage.data());
// implicitely creating an uint32_t at the same location, ending lifetime of the uint64_t there
std::uint32_t* pi32 = std::launder(reinterpret_cast(s.storage.data()));
// is there any guarantee that the value representation is unchanged?
pi64 = std::start_lifetime_as(s.storage);
// is s.storage guaranteed to be unchanged?
}
При определении pi64 я явно запускаю объект std::uint64_t, представление значения которого находится в уровень байта, тот, который я сохранил в массиве байтов.
Но затем я неявно создаю перекрывающийся std::uint32_t, который, AFAIU, завершает срок службы упомянутого std::uint64_t.
Что происходит с базовыми байтами? Каковы стандартные правила (я знаю, что беззнаковый символ/
Код: Выделить всё
std::byteУ массивов Я оставляю исходный вопрос выше, но относительно https://stackoverflow.com/a/61442225 /21691539, этот фрагмент не имеет смысла, поскольку std::uint32_t* pi32 = std::launder(reinterpret_cast(s.storage.data())); это не так, вопреки моему утверждению выше — повторное использование хранилища.
Осмысленный фрагмент будет выглядеть так:
Код: Выделить всё
#include
#include
#include
#include
struct S {
alignas(std::uint64_t) alignas(
std::uint32_t) std::array storage = {
some init values};
};
int main() {
S s;
// explicitly creating an uint64_t at the storage location
std::uint64_t* pi64 =
std::start_lifetime_as(s.storage.data());
// explicitly reusing storage, thus ending the uint64_t lifetime
new (storage.data()) std::byte[sizeof(std::uint64_t)];
// implicitely creating an uint32_t at the same location, ending lifetime of
// the uint64_t there
std::uint32_t* pi32 =
std::launder(reinterpret_cast(s.storage.data()));
// explicitly re-creating an uint64_t at the storage location
// is it sufficient to end the uint32_t lifetime or do I need an explicit
// storage reuse as above?
pi64 = std::start_lifetime_as(s.storage);
// is s.storage guaranteed to be unchanged?
}
Обратите внимание, что этот фрагмент все еще может быть неправильным, см. комментарий перед вторым std::start_lifetime_as. Кто-то может сказать мне в комментарии, нужна ли мне дополнительная строка для завершения срока службы std::uint32_t, и я соответствующим образом исправлю фрагмент.
Подробнее здесь: https://stackoverflow.com/questions/791 ... -low-level
Мобильная версия