void* или char* для общего представления буфера?
Я разрабатываю класс буфера, целью которого является представление куска памяти.
мой базовый буфер char*
(ну,boost::shared_array<char>
на самом деле, но это неважно).
Я застрял в решении, какой прототип выбрать для моего конструктора:
должен ли я пойти с:
Buffer(const void* buf, size_t buflen);
или:
Buffer(const char* buf, size_t buflen);
или что-то еще ?
что обычно делается и почему ?
6 ответов
интерфейс API более понятен для пользователя, если буфер имеет тип void*, а строка имеет тип char*. Сравнить функции memcpy и strcpy и определений функций.
для конструктора и других функций API, преимущество void*
заключается в том, что он позволяет вызывающему объекту передавать указатель на любой тип без необходимости делать ненужное приведение. Если это имеет смысл для вызывающего абонента, чтобы иметь возможность передать в любом типе, то void*
предпочтительнее. Если это действительно имеет смысл только для вызывающего абонента, чтобы иметь возможность передать char*
, затем используйте этот тип.
C++17
в C++17 введен std::byte
специально для этого.
его определение на самом деле все просто: enum class byte : unsigned char {};
.
Я, как правило, используется unsigned char
в качестве базовой структуры (не хочу, чтобы signedness испортил мой буфер по какой-то причине). Однако я обычно typedefed это:
// C++11
using byte = unsigned char;
// C++98
typedef unsigned char byte;
а затем обратитесь к нему как byte*
, которое хорошо передает смысл, на мой взгляд, лучше, чем любой из них!--5--> или void*
по крайней мере.
Я бы предпочел char*
, потому что для меня лично он лучше играет с "буфером". void*
больше похоже на "указатель на Я не знаю, что". Кроме того, это то, что лежит в основе всего.
Я бы рекомендовал uint8_t, который определен в stdint.h. Это в основном то же самое, что и "typedef unsigned char byte"; что рекомендовали другие, но у него есть преимущество быть частью стандарта C.
Что касается void*, я бы использовал это только для полиморфизма. то есть. Я бы назвал что-то указателем пустоты, если бы еще не знал, на что оно будет указывать. В вашем случае у вас есть массив байтов, поэтому я бы обозначил его как таковой, используя uint8_t* как тип.
предпочитаю unsigned char *
или uint8_t *
для буферных реализаций, так как void *
имеет раздражающее ограничение, что вы не можете выполнить математику указателя на нем. Поэтому, если вы хотите обработать некоторые данные с некоторым смещением от буфера или просто разбить буфер на куски или что-то еще, вы все равно застряли в каком-то другом типе, чтобы сделать математику.
предпочитаю unsigned char *
или uint8_t *
над равниной char *
из-за специальные правила по поводу сглаживания и char *
, который имеет потенциал, чтобы серьезно pessimize несколько петель, работающих на вашем буферов.