为什么交换不在C ++中使用Xor操作

时间:2012-05-11 09:53:34

标签: c++

我了解到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 ++。

5 个答案:

答案 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()的每个特化都必须确保它存在,或者定义一个,这可能会在名称查找时产生比值得更多的混淆它。当然,如果此类运算符已经存在,则它不一定具有正确的行为,并且最终可能会导致性能下降,因为此类重载不一定是inlineconstexpr