我了解到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 ++。
我知道Xor操作可用于实现有效的交换功能
恐怕你学错了。 XOR交换已过时:如果可靠地比使用临时值快,那么它就不应该在现代的编译器和处理器上使用(“现代”指的是大约20年或更长时间)。您说这对您来说更快,也许您应该显示基准代码,看看其他人是否得到相同的结果。
除了您的代码仅适用于整数类型之外,它还具有一个基本的错误。尝试使用您的swap版本:
int a = 1;
swap(a,a);
std::cout << a << '\n';
并且效果取决于您在哪里使用它。
在普通cpu上,两个整数变量的普通交换看起来像
$1 <- a
$2 <- b
a <- $2
b <- $1
4个操作,2个加载,2个存储,并且最长依赖项是2
以异或方式:
$1 <- a
$2 <- b
$3 <- $1 ^ $2
$4 <- $3 ^ $2
$5 <- $3 ^ $4
a <- $5
b <- $4
7个操作,2个加载,2个存储,3个逻辑,并且最长依赖性为4
因此,至少在正常情况下,即使使用xor交换也较慢。
我认为最明显的原因是XOR运算符仅对整数类型有意义。
当然,因为xor
技巧适用于POD类型。
如果要交换两个用户定义的复杂类型,则xor
将不起作用。您需要原始存储器的深层副本,而不是直接副本,这类似于xor
所做的。
编辑:
我在VC ++ 2010上进行了测试,第一个完成速度更快(并且比std :: swap更快)。
真的吗?您是否在调试模式下编译?您的结果如何?
首先,仅对整数类型定义XOR运算符。
第二,您可以使用强制转换技巧将非整数类型转换为整数形式。
但是,除POD类型外,所有其他类型都会导致未定义的行为,
第四,对于XOR操作的大小/对齐方式没有很好的支持的类型,将需要更多的调整(循环是最不邪恶的)。
您可能使operator^
重载,但这意味着swap()
的每个特殊化都必须确保它的存在或定义一个,并且这可能会使名称查找产生比其价值更大的混乱。当然,如果已经存在这样的运算符,则它不一定具有正确的行为,并且由于这种重载不一定是inline
或constexpr
,您可能会因此而获得较差的性能。