Глядя на исходный код Throwable :
187 /**
188 * The throwable that caused this throwable to get thrown, or null if this
189 * throwable was not caused by another throwable, or if the causative
190 * throwable is unknown. If this field is equal to this throwable itself,
191 * it indicates that the cause of this throwable has not yet been
192 * initialized.
193 *
194 * @serial
195 * @since 1.4
196 */
197 private Throwable cause = this;
Итак, я думаю, что то, что вы видите, является Исключением, которое было создано без использования одного из конструкторов, который принимает Причина.
Вы увидите это в отладчике, но getCause не заботится о возврате рекурсивной ссылки:
414 public synchronized Throwable getCause() {
415 return (cause==this ? null : cause);
416 }
Вам будет нужна длина буфера. После того как Вы делаете, мы можем сделать это:
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-стиля: добавленная гибкость может вызвать страдания, когда тип указателя изменяется.
Примечание: Я соглашаюсь с общей конвенцией не кастинга как можно больше. Однако без любого источника, если, это является лучшим, я мог сделать.
Вы не можете просто бросить a void*
к a std::vector<unsigned char>
потому что расположение памяти последнего включает другие объекты, такие как размер и число байтов, в настоящее время выделяемых.
Принятием буфера указывают buf
и его длина n
:
vector<unsigned char> vuc(static_cast<char*>(buf), static_cast<char*>(buf) + n);
создаст копию буфера, который можно безопасно использовать.
[РЕДАКТИРОВАНИЕ: Добавленный 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 ()".
использование станд.:: векторный класс для уже выделенного буфера не является решением. Станд.:: векторный объект управляет памятью и освобождает ее во время разрушения.
Сложное решение могло бы состоять в том, чтобы записать Ваше собственное средство выделения, которое использует уже выделенный буфер, но необходимо быть очень осторожными на нескольких сценариях, как векторное изменение размеров, и т.д.
Если у Вас есть та пустота* буфер, связанный через некоторые API-функции C, то можно забыть о преобразовании в станд.:: вектор.
При необходимости только в копии того буфера она может быть сделана как это:
std::vector< unsigned char> cpy(
(unsigned char*)buffer, (unsigned char*)buffer + bufferSize);
где bufferSize является размером в символах скопированного буфера.