提问人:city 提问时间:1/25/2013 最后编辑:Yangcity 更新时间:10/27/2013 访问量:321
为什么 swap() 在我不用两个指针调用它时可以很好地工作?
why swap() can work well when I don't call it with two pointer?
问:
#include <iostream>
using namespace std;
void swap(int *a, int *b) {
*a = *a^*b;
*b = *a^*b;
*a = *a^*b;
}
int main()
{
int array[]={1,9,2,8,3,7};
for(int i=0; i<6; i++)
cout<<array[i];
cout<<endl;
swap(array[1], array[4]);
for(int i=0; i<6;i++)
cout<<array[i];
cout<<endl;
return 0;
}
以上是测试样品。我发现如果我使用 ,它也会交换数组中两个位置的值。但这让我感到困惑,因为该函数需要两个指针,而不是两个整数值。swap(array[1], array[4]);
swap()
感谢您的帮助:)
答:
它不使用你的 ,而是 .swap
std::swap
尝试将其称为 as,您将收到错误。::swap(array[1], array[4]);
这就是为什么不好。using namespace std;
using namespace std;
这是你的罪魁祸首。导入命名空间时,将获得该命名空间中声明的每个标识符,可能包括 .std::
std::swap
因此,您是在(从标准库)而不是(从您的程序)调用。std::swap<int>(int&,int&)
::swap(int*,int*)
故事的寓意是:永远不要说。它太大了。using namespace std;
评论
using namespace std;
这就是为什么你应该避免.using namespace std;
包含标准标头显然已将声明拖入程序中;并已将其转储到全局命名空间中。所以你的代码是在调用它,而不是你的版本。std::swap
using namespace std;
您的问题与 无关。问题在于,您正在将对 int () 的左值引用传递给在 和 上重载的函数。如果删除了 using 指令,则不会调用自己的 swap;事实上,您的代码无法编译,因为 C++ 不允许从指针到 int 的隐式转换。为了使用您的函数,您必须将其称为using namespace std;
int&
int&
int*
swap(&array[1], &array[4]);
现在,如果您更正了函数调用以反映这一点,那么无论是否存在 using 指令,它都应该可以工作。但是,我建议不要这样做;的语义是交换两个引用,而不是指针。重载具有不兼容语义的标准函数不仅会让熟悉标准库的人感到困惑,而且很可能会破坏使用 on 的完全有效的代码。std::swap
std::swap
int*
你可能会想,“但这只有在他们这样做的情况下才会发生,而他们永远不应该这样做。然而,信不信由你,正是那种你确实想要使用指令的应用程序(当然,范围是正确的)。这样做的原因是,用户代码可能完全可以执行您要执行的操作:使算法专用化。如果一些库代码简单地说,任何用户定义的重载都会被忽略,使该重载变得毫无用处。相反,如果你的代码看起来像using namespace std;
swap
swap
std::swap
template <typename T>
void foo (T& a, T& b)
{
using std::swap; // Or simply namespace std;
// ...
swap (a, b);
// ...
}
编译器将能够正确使用 ADL 并为任何给定的 T(例如,)选择用户定义的交换,同时仍然能够用于其他 T。int
std::swap
换言之:始终提供引用参数,并在需要交换模板化类型时使用作用域化 using 声明。swap
评论
If you removed the using directive, you would not be calling your own swap
什么?!ADL与它有什么关系?!参数是 .int
int
int*
int
int*
swap
std
int&
swap
std
int&
using
swap
swap(array[1], array[4]);
swap
int*
swap
你会提供另一个答案来解决这个问题,没有临时变量吗?
我认为这是不可能做到的。无论如何,“没有临时变量”的要求从何而来?你认为临时变量会让你的代码变慢吗?让我们看看这里是否是这种情况。
图表 A:一些黑客。不是很明显它是如何工作的。无法正确地将变量与自身交换:
void swap1(int* a, int* b)
{
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
生成的汇编代码:
movl (%rsi), %eax
xorl (%rdi), %eax
movl %eax, (%rdi)
xorl (%rsi), %eax
movl %eax, (%rsi)
xorl %eax, (%rdi)
图表 B:带有临时变量的简单代码。它可以正确地将变量与自身交换:
void swap2(int* a, int* b)
{
int c = *a;
*a = *b;
*b = c;
}
生成的汇编代码:
movl (%rdi), %eax
movl (%rsi), %edx
movl %edx, (%rdi)
movl %eax, (%rsi)
临时变量解决方案更易于理解,可以处理所有情况,并导致代码速度更快。
同样,在面试情况之外,xor 技巧是完全没用的。如果我是面试官,而候选人知道 xor 技巧,但没有通过说“这是一个可爱的技巧,但我永远不会在现实世界中使用它”来限定它,我肯定不会雇用他。让我用一句话来结束这个答案:
每次都胜过聪明。拉里·奥斯特曼
评论
endl
'\n'
endl
\n
std::endl
int i = 42; swap(&i, &i);
i