Размер - это количество элементов, присутствующих в векторе
Емкость - это объем пространства, которое вектор использует в настоящее время.
Давайте разберемся с этим на простом примере:
using namespace std;
int main(){
vector<int > vec;
vec.push_back(1);
vec.push_back(1);
vec.push_back(1);
cout<<"size of vector"<<vec.size()<<endl;
cout<<"capacity of vector"<<vec.capacity()<<endl;
return 0;
}
в настоящее время размер равен 3, а емкость равна 4.
Теперь, если мы отодвинем еще один элемент,
using namespace std;
int main(){
vector<int> vec;
vec.push_back(1);
vec.push_back(1);
vec.push_back(1);
vec.push_back(1);
cout<<"size of vector"<<vec.size()<<endl;
cout<<"capacity of vector"<<vec.capacity()<<endl;
return 0;
}
теперь размер равен: 4 емкость равна 4
теперь, если мы попытаемся вставить еще один элемент в vector
, то размер станет 5, но вместимость станет 8.
это происходит на основе типа данных vector
, как здесь, в этом случае vector
для типа int
, так как мы знаем, что размер int
составляет 4 байта, поэтому компилятор выделит 4 блока памяти .. и когда мы пытаемся добавить 5-й элемент, vector::capacity()
удваивается, что мы имеем в настоящее время.
то же самое продолжайте .. например: если мы попытаемся вставить 9-й элемент, то размер vector
будет 9, а емкость b 16 ..
Нет. Тип возвращаемого значения функции C ++ может изменяться только в зависимости от явных параметров шаблона или типов ее аргументов. Он не может изменяться в зависимости от значения его аргументов.
Однако вы можете использовать различные методы для создания типа, который является объединением нескольких других типов. К сожалению, это не обязательно поможет вам здесь, поскольку одна из таких техник сама по себе является void *, и вернуться к исходному типу будет сложно.
Однако, вывернув проблему наизнанку, вы можете получить то, что хотите. Я полагаю, вы захотите использовать опубликованный вами код как что-то вроде, например:
void bitmap_operation(void *data, int depth, int width, int height) {
some_magical_type p_pixels = returnPointer(data, depth);
for (int x = 0; x < width; x++)
for (int y = 0; y < width; y++)
p_pixels[y*width+x] = some_operation(p_pixels[y*width+x]);
}
Поскольку C ++ должен знать тип p_pixels во время компиляции, это не будет работать как есть. Но что мы можем сделать, так это сделать сам bitmap_operation шаблоном, а затем обернуть его переключателем в зависимости от глубины:
Если вы можете использовать аргумент шаблона вместо обычного параметра, вы можете создать шаблонную функцию, которая возвращает правильный тип для каждого значения глубины
. Во-первых, необходимо некоторое определение правильного типа согласно depth
. Вы можете определить шаблон со специализациями для разных размеров битов:
// template declaration
template<int depth>
struct uint_tmpl;
// specializations for certain types
template<> struct uint_tmpl<8> { typedef uint8_t type; };
template<> struct uint_tmpl<16> { typedef uint16_t type; };
template<> struct uint_tmpl<32> { typedef uint32_t type; };
Это определение можно использовать для объявления шаблонной функции, которая возвращает правильный тип для каждого битового значения:
// generic declaration
template<int depth>
typename uint_tmpl<depth>::type* returnPointer(void* ptr);
// specializations for different depths
template<> uint8_t* returnPointer<8>(void* ptr) { return (uint8_t*)ptr; }
template<> uint16_t* returnPointer<16>(void* ptr) { return (uint16_t*)ptr; }
template<> uint32_t* returnPointer<32>(void* ptr) { return (uint32_t*)ptr; }
Нет; вы не можете сделать это в C ++. Правильный ответ - вернуть void *
.
Подумайте об этом с противоположной стороны вызова - и с точки зрения компилятора:
Как компилятор сможет проверить, правильно ли используется возвращаемое значение (например, присвоено переменной правильного типа), если он не может знать, какой из трех возвращаемых типов будет возвращен?
В этот момент понятие присваивания " один из нескольких типов "возвращаемого значения становится бессмысленным. У возвращаемого типа функции нет другой цели в жизни, кроме как дать компилятору возможность выполнять свою работу; компилятору нужен «один» тип, чтобы иметь возможность выполнять проверку типов. Поскольку вы не знаете, какой именно, до времени выполнения, компилятор может ' Я провожу проверку типов за вас. Вы должны сказать компилятору «прекратить попытки» сопоставить возвращаемое значение с любым конкретным типом указателя - следовательно, вернуть void *
.
Если ваши аргументы глубины известны во время компиляции, вы в качестве альтернативы можно использовать набор шаблонов, таких как @sth , продемонстрированный, или использовать набор отдельных независимых функций, или использовать набор связанных функций, которые вызывают общую функцию реализации и затем приводят возвращаемый результат к правильному типу. Какой из них вы выберете - это в основном эстетическое решение.
Если значение depth
не известно до времени выполнения, вам, вероятно, следует вернуть void *
.
Теперь я предполагаю, что ваша фактическая реализация действительно что-то делает для создания указателя, а не то, что показывает ваш пример кода. Ваш пример кода не является реальной функцией; это больше похоже на попытку повторить то, что делает приведение
. Приведение
не является вызовом функции; это директива компилятора, чтобы попытаться «преобразовать» его операнд в определенный тип (именно «как», это длинная история для другого поста). Это не операция языка C ++, а операция компилятора. Вы не можете переписать это на самом C ++.
You can allocate some memory on the heap, and return a void* that you cast to the type that was allocated. Its a dangerous and unsafe way of working and is an old C trick.
You could return a union that contains all valid datatypes (and a selection indicator).
You could use templates, which is the recommended C++ way for this kind of thing.
You could provide a set of overloaded functions that take a parameter (of each type) as a reference - the compiler will decide which function to call based on the datatype. I often prefer this way as I think its the simplest.
вы можете сделать это:
if (depth == 8) (uint8 *) returnPointer (void * ptr, int depth) {// etc