我了解到Xor操作可用于实现有效的交换功能。像这样:
template<class T>
void swap(T& a, T& b)
{
a = a^b;
b = a^b;
a = a^b;
}
但是我可以在互联网上找到的互换实现基本上是这样的:
template<class T>
void swap(T& a, T& b)
{
T temp(a);
a = b;
b = temp;
}
似乎编译器没有为上面的两个表单生成相同的代码,因为我在VC ++ 2010上测试了它,第一个更快地完成了工作(并且比std :: swap更快)。第一个是便携式还是其他任何问题?随意纠正我的任何错误,因为我不是英国人,也不擅长C ++。
答案 0 :(得分:18)
我已经了解到Xor操作可用于实现有效的交换功能
你知道错了,我很害怕。 XOR交换过时了:如果它比使用临时值可靠得快,那么它不应该出现在现代编译器和处理器上(其中“现代”我的意思大致是过去20年或更长时间)。你说它对你来说更快,可能你应该显示你的基准代码,看看其他人是否得到相同的结果。
除了您的代码仅适用于整数类型的事实,它有一个基本的错误。请尝试使用您的swap版本:
int a = 1;
swap(a,a);
std::cout << a << '\n';
答案 1 :(得分:10)
效果取决于你使用它的位置。
在正常的cpu上,两个整数变量的正常交换看起来像
$1 <- a
$2 <- b
a <- $2
b <- $1
4个操作,2个加载,2个存储和最长的依赖性是2
以xor方式:
$1 <- a
$2 <- b
$3 <- $1 ^ $2
$4 <- $3 ^ $2
$5 <- $3 ^ $4
a <- $5
b <- $4
7个操作,2个加载,2个存储,3个逻辑和最长的依赖性是4
因此,即使适用,至少通常与xor交换也会更慢。
答案 2 :(得分:4)
我认为最明显的原因是XOR运算符只对整数类型有意义。
答案 3 :(得分:2)
当然,因为xor
技巧适用于POD类型。
如果要交换两个用户定义的复杂类型,xor
将不起作用。你需要一个深拷贝,而不是原始内存的直接拷贝,这是xor
所做的。
编辑:
我在VC ++ 2010上测试了它,第一个是更快地完成工作(并且比std :: swap更快)。
真的?你在调试模式下编译了吗?你有什么结果?
答案 4 :(得分:0)
首先,仅为整数类型定义XOR运算符。
其次,您可以使用强制转换技巧将非整数类型转换为整数形式。
但第三,除了POD类型之外的所有类型都会导致未定义的行为,
,第四,对于XOR操作没有良好支持的大小/对齐的类型,需要更多的twiddling(循环是最不邪恶的)。
您可以重载operator^
,但这意味着swap()
的每个特化都必须确保它存在,或者定义一个,这可能会在名称查找时产生比值得更多的混淆它。当然,如果此类运算符已经存在,则它不一定具有正确的行为,并且最终可能会导致性能下降,因为此类重载不一定是inline
或constexpr
。