большая вещь об этом состоит в том, что это относится к элементу, в котором Вы в настоящее время находитесь - Вы не должны выбирать целую строку кода VB для комментария его, например, Вы просто вводите Ctrl + K , Ctrl + C для комментария текущей строки. На aspx странице можно прокомментировать большой блок кода - например, всего ListView - просто идя в первую строку и поражая Ctrl + K , Ctrl + C .
Использование алгоритма обмена xor
void xorSwap (int* x, int* y) {
if (x != y) { //ensure that memory locations are different
*x ^= *y;
*y ^= *x;
*x ^= *y;
}
}
Зачем нужен тест?
Тест должен гарантировать, что x и y имеют разные ячейки памяти (а не разные значения) . Это потому, что (p xor p) = 0
, и если и x, и y используют одну и ту же ячейку памяти, когда один установлен в 0, оба устанавливаются в 0.
Когда и * x, и * y равны 0, все остальные операции xor для * x и * y будут равны 0 (поскольку они одинаковы), что означает, что функция установит для * x и * y значение 0.
Если у них одинаковые значения, но не одно и то же место в памяти, все работает, как ожидалось
*x = 0011
*y = 0011
//Note, x and y do not share an address. x != y
*x = *x xor *y //*x = 0011 xor 0011
//So *x is 0000
*y = *x xor *y //*y = 0000 xor 0011
//So *y is 0011
*x = *x xor *y //*x = 0000 xor 0011
//So *x is 0011
Следует ли это использовать?
В общих случаях нет. Компилятор оптимизирует временную переменную и, учитывая, что замена является обычной процедурой, он должен выводить оптимальный машинный код для вашей платформы.
Возьмем, к примеру, эту программу быстрой проверки, написанную на C.
#include <stdlib.h>
#include <math.h>
#define USE_XOR
void xorSwap(int* x, int *y){
if ( x != y ){
*x ^= *y;
*y ^= *x;
*x ^= *y;
}
}
void tempSwap(int* x, int* y){
int t;
t = *y;
*y = *x;
*x = t;
}
int main(int argc, char* argv[]){
int x = 4;
int y = 5;
int z = pow(2,28);
while ( z-- ){
# ifdef USE_XOR
xorSwap(&x,&y);
# else
tempSwap(&x, &y);
# endif
}
return x + y;
}
Скомпилировано с использованием:
gcc -Os main.c -o swap
Версия xor принимает
real 0m2.068s
user 0m2.048s
sys 0m0.000s
, а версия с временной переменной принимает:
real 0m0.543s
user 0m0.540s
sys 0m0.000s
Глупые вопросы заслуживают соответствующих ответов:
void sw2ap(int& a, int& b) {
register int temp = a; // !
a = b;
b = temp;
}
Единственное хорошее использование ключевого слова register
.
Как уже отмечалось в manu, алгоритм XOR - популярный алгоритм, который работает для всех целочисленных значений (включая указатели, с некоторой удачей и приведением типов). Для полноты картины я хотел бы упомянуть еще один менее мощный алгоритм с добавлением / вычитанием:
A = A + B
B = A - B
A = A - B
Здесь нужно быть осторожным с переполнением / потерей данных, но в остальном он работает так же хорошо. Вы можете даже попробовать это с числами с плавающей запятой / удвоением, если XOR для них запрещен.
в общем виде:
A = A operation B
B = A inverse-operation B
A = A inverse-operation B
, однако, вы должны потенциально остерегаться переполнения, а также не все операции имеют инверсию, которая хорошо определена для всех значений, для которых определена операция. например, * и / работают до тех пор, пока A или B не станут равными 0
xor особенно приятен, поскольку он определен для всех целых чисел и является собственным обратным
Никто еще не предлагал использовать std :: swap
.
std::swap(a, b);
Я не использую никаких временных переменных и в зависимости от типа a
и b
реализация может иметь специализацию, которой также нет. Реализация должна быть написана с учетом того, уместен ли «трюк». Нет смысла делать второе предположение.
В более общем плане, я, вероятно, хотел бы сделать что-то подобное, так как это будет работать для типов классов, позволяющих ADL найти лучшую перегрузку, если это возможно.
using std::swap;
swap(a, b);
Конечно, Реакция собеседника на такой ответ может многое сказать о вакансии.