我想知道在操作方面,交换整数的方式最有效的是c ++,为什么?是这样的:
int a =..., b = ...;
a = a + b;
b = a - b;
a = a - b;
比使用临时更有效?还有其他更有效的方法吗? (不要求其他方式交换整数)以及为什么它们会更有效率?
答案 0 :(得分:6)
最好的方法是信任编译器和使用C ++标准库函数。它们是为彼此设计的。
std::swap
将获胜。
您可以对int
使用XOR交换(不需要临时),但是现在它的执行效果仍然不如std::swap
。
答案 1 :(得分:4)
分配值总是比进行算术运算更快。
对于std :: swap的template<typename T> void swap(T& t1, T& t2) {
T temp = std::move(t1); // or T temp(std::move(t1));
t1 = std::move(t2);
t2 = std::move(temp);
}
所以使用临时变量比做算术技巧要好 而使用std :: swap则更好,因为在编程中重新发明轮子永远不是一个好主意
答案 2 :(得分:1)
在我的情况下,std::swap
比以下速度慢5%(均使用O3优化)。通常,std :: swap()函数将调用复制构造函数,该复制构造函数可能总是比仅复制部分内存要慢。
#include <cstring>
size_t objectSize = sizeof(Object);
Object *temp = (Object *) malloc(objectSize);
loop {
loop {
memcpy(temp, a, objectSize);
memcpy(a, b, objectSize);
memcpy(b, temp, objectSize);
}
}
答案 3 :(得分:0)
doxygen.conf
答案 4 :(得分:0)
最有效的方法是不要自己去做。 这实际上取决于您为什么/要这样做。尝试变得聪明并用C ++编写晦涩的代码只会减少编译器正确优化代码的机会。
让我们说我们使用您所写的±方式: 首先,必须从内存中加载值a和b。 然后,您将执行3个算术运算来“交换”它们的内容。 最后,这两个值必须再次存储在内存中。 (不要使用实际的汇编代码,因为我不太熟悉它,所以这种伪汇编更容易理解)
load a into register rA
load b into register rB
add rB to rA and store in rA
subtract rB from rA and stor in rB
subtract rB from rA and store in rA
store register rA to memory b
store register rB to memory a
如果编译器将完全按照您的要求进行操作(可能他会忽略它并使它变得更好),则将是: 2次加载,3次简单的数学运算,2次存储-7次操作。
它也可以做得更好,因为可以使用内存中的1个值进行加/减。
load 'a' into register rA
add b to rA and store in rA
subtract b from rA and store in rB
subtract rB from rA and store in rA
store rA to a
store rB to b
如果我们使用额外的tmp变量:
int a =..., b = ...;
int tmp = a;
a = b;
b = tmp;
编译器可能会认识到“ tmp”只是一个临时变量,仅用于交换2个值,因此它不会为它分配一个仅使用寄存器的内存位置。 在这种情况下,它会执行以下操作:
load a into register rA
load b into register rB
store register rA to memory b
store register rB to memory a
仅4个操作-基本上,它可以最快地完成此操作,因为您需要加载2个值,并且需要存储2个值,而没有其他操作。 (对于现代的nx86_64处理器,没有命令会在内存中交换2个值-其他体系结构可能会拥有它,并且在这种情况下甚至更快)。
执行这些算术运算(或xor-trick)是一种很好的练习,但是在具有最基本编译器的所有现代x86 CPU上,任何形式的“效率都不会更高”。 它将使用相同数量的寄存器,相同数量的变量存储空间,但需要更多指令来完成相同的工作。 通常,除非您已经检查了代码,对其进行了测试并对其进行了基准测试,并发现生成的程序集不尽如人意,否则,您不应尝试使编译器的性能超出正常范围。
但是几乎不需要进行优化,您的时间最好花在看大图上。