特殊情况:交换两个变量
的值(对于一般的解决办法,见下文)
在C交换两个变量的值++,你应该总是使用swap
:
using std::swap;
swap(x, y); // Do NOT say: std::swap(x, y) -- Read about Koenig lookup!
不要打扰如何它会这样做;它会这样做非常快。如果处理器支持它(但标准没有告诉实现这么做),C++标准库的实现将尽最大努力将其优化为单指令。对于只寄存器变量,例如有x86指令xchg
,它将尽可能快地完成它。不要试图用一些“三个xor操作”来调整它,它不会更快。如果你不走运,它不会被优化到像xchg
这样的东西。
C++ 03中的通用swap
操作引入了一个临时变量并执行三个复制构造。在C++ 11中,存在移动语义,并且对象比被复制移动的更多。为了您自己的类型,假设其只持有一个指向实际数据的一些数据结构,你应该优化这个过程,使其在固定的时间进行:
在C++ 03,您可以专门致力于std::swap
或在您的名称空间(see the two top answers on this question)中实现您自己的swap
函数来优化交换:只需交换班级中的每个成员即可交换其数据。对于仅保存指针的数据结构示例,只需交换指针即可。
在C++ 11,也有新的移动语义,它允许你从一个到另一个对象,这将导致一个非常类似的行为,实现数据的移动。 (移动语义已经引入了更为普遍的问题,如交换两个对象:如果不再需要一个对象,但另一个对象必须是第一个对象的“复制”,则可以简单地移动它。)阅读有关移动语义和移动构造函数获取细节。
对于两个C++ 03和C++ 11有另一种方式:您可以实现隐含共享数据和写入时复制重类的数据结构等等。在上面的例子中,你的数据结构中包含一个指向实际数据的指针,实现引用计数。复制数据结构时,只需将参考计数器加1。修改数据时,请确保它不是共享的(ref count = 1),否则只能通过复制来“分离”它。这会导致定时复制和交换操作。
一般情况:多个任意表达式
对于其他命题与不输入/输出相关的,像(a, b) = (x, y)
,只写他们“原样”,它将运行至少完美流水线,因为它们没有任何依赖性:
a = x;
b = y;
如果他们是依赖于输入/输出,就像您在编辑中的示例,您可以将其分解并引入临时对象。你不会试图用诸如xor-ing等一些奇特的表达技巧来解决这个问题。编译器知道汇编程序的很多技巧(如xchg
),你只知道用纯C++(如xor)表达的技巧。
在C++ 11,有std::tuple
和std::tie
允许你指定多个表达式,而不引入临时对象(它们将场景以保持存储在该元组中的值的后面被引入,并试图优化它们要么完全远离或在至少只使用寄存器如果可能的话,以将它们保持):
using std::tie;
using std::make_tuple;
tie(ones, twos) = make_tuple((ones^n)^~twos, (ones & n) | (twos & ~n));
。注意,类型的右手侧对/元组的有在左手侧匹配目标值作为转换不是隐含在这里。如果遇到问题,执行在右手侧的static_cast
,告诉std::make_tuple
明确的类型或只是使用的构造方法std::tuple
需要明确的类型,如:
using std::tie;
using std::tuple;
tie(ones, twos) = tuple<int,int>((ones^n)^~twos, (ones & n) | (twos & ~n));
'的std ::交换(X,Y);'是优选的方式。 – chris 2013-02-09 06:34:59
@chris:实际上,'std :: swap(x,y)'是错误的***方式。 – Mehrdad 2013-02-09 07:19:59
@Mehrdad,好点。我的重点是使用预制版本,而不是总是试图将其内联,但这是一个有效的问题。 – chris 2013-02-09 08:18:57