В какой момент будет / может быть часть о методе шаблона будет оптимизированный компилятором? Будет ли он удалить недоступный код, разверните ненужные петли? (Биты использует без знака int блоки, целое использует без знака долго из них)
Кроме того, существует ли тип данных c ++, означающий «я целое число от размера ваших реестров процессоров»?
template<size_t bits> class IntegerFactoryImpl : public IntegerFactory<Integer<bits>>{
private:
template<int sizeOfLong, int sizeOfInt> Integer<bits> getOne(const Bits& b) const{
Integer<bits> integer = this->getOne();
size_t roof = (b.blocks() > integer.size()*(sizeOfLong/sizeOfInt))? integer.size()*(sizeOfLong/sizeOfInt) : b.blocks();
for(size_t i = 0; i < roof; ++i){
integer.at(i/(sizeOfLong/sizeOfInt)) = 0;
for(size_t j = 0; j < (sizeOfLong/sizeOfInt); ++j){
if(i % (sizeOfLong/sizeOfInt) == j){
integer.at(i/(sizeOfLong/sizeOfInt)) |= ((unsigned long)b.block(b.blocks()-i-1)) << (sizeOfInt*j);
break;
}
}
}
for(size_t i = roof; i < integer.size()*(sizeOfLong/sizeOfInt); ++i){
if(i % (sizeOfLong/sizeOfInt) == 0){
integer.at(i/(sizeOfLong/sizeOfInt)) = 0;
}
}
return integer;
}
public:
virtual ~IntegerFactoryImpl() throw(){}
virtual Integer<bits> getOne() const{
return Integer<bits>();
}
virtual Integer<bits> getOne(const Bits& b) const{
return this->getOne<sizeof(unsigned long)*8, sizeof(unsigned int)*8>(b);
}
};
Будет ли разница с этим кодом (без использования шаблона):
template<size_t bits> class IntegerFactoryImpl : public IntegerFactory<Integer<bits>>{
public:
virtual ~IntegerFactoryImpl() throw(){}
virtual Integer<bits> getOne() const{
return Integer<bits>();
}
virtual Integer<bits> getOne(const Bits& b) const{
Integer<bits> integer = this->getOne();
size_t roof = (b.blocks() > integer.size()*((sizeof(unsigned long)/sizeof(unsigned int)))? integer.size()*((sizeof(unsigned long)/sizeof(unsigned int)) : b.blocks();
for(size_t i = 0; i < roof; ++i){
integer.at(i/((sizeof(unsigned long)/sizeof(unsigned int))) = 0;
for(size_t j = 0; j < ((sizeof(unsigned long)/sizeof(unsigned int)); ++j){
if(i % ((sizeof(unsigned long)/sizeof(unsigned int)) == j){
integer.at(i/((sizeof(unsigned long)/sizeof(unsigned int))) |= ((unsigned long)b.block(b.blocks()-i-1)) << ((sizeof(unsigned int)*8)*j);
break;
}
}
}
for(size_t i = roof; i < integer.size()*((sizeof(unsigned long)/sizeof(unsigned int)); ++i){
if(i % ((sizeof(unsigned long)/sizeof(unsigned int)) == 0){
integer.at(i/((sizeof(unsigned long)/sizeof(unsigned int))) = 0;
}
}
return integer;
}
};
(редактировать: я только что обнаружил, что код не работает должным образом (я исправил это), но оригинальный вопрос все еще применяется ..)
Правильно, компилятор оптимизирует все, что он может вычислить во время компиляции, и если у вас есть цикл, который повторяется только один раз (например, for(i = 0; i < 1; i++)
, это удалит петлю полностью.
Что касается целых размеров, это действительно зависит от того, что вы пытаетесь достичь, если лучше использовать long
или же int
, Например, в x86-64 64-битная операция займет дополнительный байт, чтобы указать, что следующая инструкция является 64-битной командой вместо 32-битной инструкции. Если компилятор сделал int
Длиной 64 бита код становился (чуть-чуть) больше и, следовательно, не очень хорошо подходил бы для кешей и т. Д. И т. Д. В 16-, 32- или 64-битных операциях выигрыша в скорости нет [для 99% операции, умножение и деление являются некоторыми из очевидных исключений — чем больше число, тем больше времени требуется, чтобы разделить или умножить его ((На самом деле, количество битов SET в числе влияет на время умножения, и я считаю, что деление тоже) )] в x86-64. Конечно, если вы, например, используете значения для выполнения операций битовой маски и тому подобное, используйте long
предоставит вам 64-битные операции, для выполнения которых требуется вдвое меньше операций. Это явно преимущество. Так что это «правильно» использовать long
в этом случае, даже если он добавляет дополнительный байт на инструкцию.
Также имейте в виду, что очень часто, int
используется для «меньших чисел», поэтому для многих вещей дополнительный размер int
будет просто потрачен впустую, и займет дополнительное место в кэше данных и т. д., и т. д. int
остается 32-разрядным также для сохранения размера больших целочисленных массивов и тому подобного на разумном размере.
Других решений пока нет …