Я пишу функцию для класса, который сериализует структуры, представляющие пакеты, в один буфер, который затем отправляется игрокам в многопользовательской игре. Чтобы сохранить эту функцию как можно более универсальной, я подумал, что было бы неплохо зарезервировать буфер для хранения структур и предоставить шаблонную функцию, которая построит структуру в буфере и вернет ссылку на нее. Вот что я пробовал ...
template <typename T>
T& writePacket()
{
auto addr = m_writeOffset;
*m_writeOffset = T();
m_writeOffset += sizeof(T);
return *addr;
}
Где m_writeOffset - указатель u8 * на следующий доступный байт.
Я уверен, что вернуть указатель на место в буфере, где находится структура, было бы намного проще, однако каждая из моих стоек пакетов содержит статический байт для заголовка, который позволяет клиентам идентифицировать типы пакетов. Вот несколько примеров пакетов, которые я могу отправить:
typedef u8 packet_header;
#pragma pack(push, 1)
struct CP_AttackEntity
{
static const packet_header header = 0;
u16 targetUID;
};
#pragma pack(pop)
#pragma pack(push, 1)
struct CP_EntityMoved
{
static const packet_header header = 3;
u16 uid;
Vec2<u16> pos;
};
#pragma pack(pop)
u8, u16 - это просто typedef для uint8_t и т. д.
Я предполагаю, что причина, по которой это не работает, исходит из того, что я не совсем понимаю, как работают конструкторы. Когда пакет отправляется сервером или получен клиентом, пакеты полностью обнуляются. Может ли кто-нибудь указать мне правильное направление? Спасибо!
Можете ли вы дать минимальный воспроизводимый пример фактического кода, который вызывает все 0? *m_writeOffset = T(); выглядит как неопределенное поведение, и мне любопытно, как он вообще компилируется.
Так ли это? Я думал, что static означал бы, что переменная в каждом экземпляре структуры будет инициализирована определенным значением.
Неа. У статической переменной класса есть имя, которое передается классу (так что все объекты этого типа могут получить к нему доступ), но это единый объект, совместно используемый всеми экземплярами вне класса. Где-то у вас должен быть файл cpp, где у вас const packet_header CP_EntityMoved::header = 3;.
Вы хотите выполнить поиск в Google по запросу "новое место размещения". Вы можете начать здесь, как хороший пример.
Вау! Это именно то, что я искал! Я изменю свой код, чтобы отразить обе ваши идеи, и расскажу, как это работает. Кроме того, я мог поделиться кодом сборки моей исходной функции с Натаном Оливером.
Также прочтите Обычные старые типы данных. Вы можете создать тривиальный конструктор, который инициализирует байт заголовка для вашего тега.





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