Интерес в том, что даже unsigned char не подходит для подмены. Стандартом разрешены только char и std::byte.
Ok, let's get truly pedantic. After reading this, this and this, I'm pretty confident that I understand the intention behind both Standards.
So, doing reinterpret_cast from std::uint8_t* to char* and then dereferencing the resulting pointer is safe and portable and is explicitly permitted by [basic.lval].
However, doing reinterpret_cast from char* to std::uint8_t* and then dereferencing the resulting pointer is a violation of strict aliasing rule and is undefined behavior if std::uint8_t is implemented as extended unsigned integer type.
Нет, если вы не вызвали конструктор и обратились к объекту, вы схлопочете UB, формально говоря.
Да и какой смысл в том, чтобы навыделять памяти, а конструкторы не вызывать? Это нарушает принцип RAII как минимум.
Кстати, именно статической памяти я в вашем коде не увидел.
class Example
{
private:
uint8_t * someSelfAliasableMember;
int a;
int b;
int c;
public:
Example() : someSelfAliasableMember(new uint8_t[100]) {}
void doSomething() __restrict
{
for (int32_t i = 0; i < 10; ++i)
{
someSelfAliasableMember[i] = i;
}
}
};
Тут проблема не в том, что член класса char*, а в том, что запись идет в char*, и из-за strict aliasing правил - это может быть запись куда угодно, в том числе в &this. Кешировать пришлось бы любой член структуры, любого типа.
Эту же проблему можно воспроизвести в меньшем масштабе, если у вас в цикле есть запись в int* и чтение какой-то другой не меняющейся int переменной. Особенно, когда переменная в куче и указатель пришел в параметре функции.
static void InterpolateSnapshot_Hermite_WithExtrapolation( float t,
float step_size,
float extrapolation,
const __restrict CubeState * a,
const __restrict CubeState * b,
__restrict view::ObjectUpdate * output )
Если нет необходимости в подобной локальной переменной, то не нужно "кэшировать".
На уровне ассемблера все обращения к памяти происходят через регистры, так что в любом случае адрес из указателя будет записан в регистр и этот регистр будет индексироваться.
Частично это можно решить кешированием, можно попробовать поменять типы кое где.
void method () __restrict {}
) не является эквивалентным кэшированию в локлаьную переменную ? за исключением того, что ничего кэшировать не придётся, так как компилятор уже будет знать, что переменная ни с чем в рамках данного метода не overlapp'ится" в памяти ?
floppa322, Если это статический метод Example/ExtremelyHeavyObjectBuilder/ExtremelyHeavyObject, то можете так делать.
В случае статического метода ExtremelyHeavyObjectBuilder/ExtremelyHeavyObject требуется указать класс, т.е. будет что-то вроде ExtremelyHeavyObjectBuilder::createObj().
Так же createObj может быть и свободной функцией.
Правильно ли я понял, что если значение wide type будет находиться в допустимом диапазоне для narrow type, то результат будет так сказать "полностью defined", как будто типы изначально были одинаковые ?