У меня есть буфер (void*)
, который мне нужно преобразовать в std::vector<unsigned char>
, прежде чем я смогу его передать. К сожалению, мои навыки приведения C++ немного слабы. Какие-либо предложения?
Преобразование (void*) в std::vector‹unsigned char›
Ответы (4)
Вам понадобится длина буфера. Как только вы это сделаете, мы можем сделать это:
unsigned char *charBuf = (unsigned char*)voidBuf;
/* create a vector by copying out the contents of charBuf */
std::vector<unsigned char> v(charBuf, charBuf + len);
Хорошо, комментарий заставил меня задуматься, почему я не использовал reinterpret_cast
:
В C++ приведение в стиле C является удобной функцией — она просит компилятор выбрать наиболее безопасную и переносимую форму преобразования из набора доступных операторов приведения.
reinterpret_cast
определяется реализацией и всегда должно быть последним, о чем вы думаете (и используется, когда вы сознательно делаете непереносимую вещь).Преобразование между (
unsigned
не меняет тип)char *
иvoid *
является переносимым (на самом деле вы можете использоватьstatic_cast
, если вы действительно разборчивы).
Проблема с приведением в стиле C заключается в следующем: добавленная гибкость может вызвать сердечные боли при изменении типа указателя.
Примечание. Я согласен с общим правилом не проводить кастинг как можно чаще. Однако, без указания источника, это лучшее, что я мог сделать.
Вы не можете просто привести void*
к std::vector<unsigned char>
, потому что расположение памяти последнего включает другие объекты, такие как размер и количество байтов, выделенных в данный момент.
Предположим, что на буфер указывает buf
, а его длина равна n
:
vector<unsigned char> vuc(static_cast<char*>(buf), static_cast<char*>(buf) + n);
создаст копию буфера, которую можно безопасно использовать.
[EDIT: добавлено static_cast<char*>
, необходимое для арифметики указателей.]
Единственный случай, когда это будет законным, — это если вы уже создали вектор и просто хотите вернуть его.
void SomeFunc(void* input);
main() {
std::vector< unsigned char > v;
SomeFunc((void*) &v);
}
SomeFunc(void* input) {
// Now, you could cast that void* into a vector
std::vector< unsigned char >* v_ = (vector<unsigned char>*)input
}
На самом деле я не пытался посмотреть, будет ли это работать, но в этом суть. Тем не менее, если вы делаете это с нуля, вы определенно делаете это неправильно. Это действительно плохо. Единственный раз, когда это может быть даже отдаленно понятно, - это если вы вынуждены реализовать уже определенную "SomeFunc()".
использование класса std::vector для уже выделенного буфера не является решением. Объект std::vector управляет памятью и освобождает ее во время уничтожения.
Сложное решение может состоять в том, чтобы написать свой собственный распределитель, который использует уже выделенный буфер, но вы должны быть очень осторожны в нескольких сценариях, таких как изменение размера вектора и т. д.
Если у вас есть этот буфер void*, связанный с некоторыми функциями C API, вы можете забыть о преобразовании в std::vector.
Если вам нужна только копия этого буфера, это можно сделать так:
std::vector< unsigned char> cpy(
(unsigned char*)buffer, (unsigned char*)buffer + bufferSize);
где bufferSize — размер копируемого буфера в символах.