为什么 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()
需要两个指针,而不是两个整数值。
感谢您的帮助:)
using namespace std;
这是你的罪魁祸首。导入 std::
命名空间时,将获取在该命名空间中声明的每个标识符,可能包括 std::swap
。
因此,您正在调用std::swap<int>(int&,int&)
(从标准库)而不是::swap(int*,int*)
(从您的程序)。
故事的寓意:永远不要说using namespace std;
.实在是太大了。
它不使用您的swap
,但std::swap
。
尝试将其称为 ::swap(array[1], array[4]);
,您将收到错误。
这就是为什么using namespace std;
不好。
你应该避免using namespace std;
。
包含标准标头显然已将std::swap
声明拖入程序;using namespace std;
已将其转储到全局命名空间中。所以你的代码在调用它,而不是你的版本。
你会提供另一个答案来解决这个问题,没有临时变量吗?
我认为这是做不到的。"无临时变量"的要求到底从何而来?你认为临时变量会让你的代码变慢吗?让我们检查一下这里是否是这种情况。
图表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)
临时变量解决方案更易于理解,可处理所有情况并生成更快的代码。
同样,在面试情况之外,异或技巧是完全无用的。如果我是面试官,候选人知道异或技巧,但没有说"这是一个可爱的把戏,但我永远不会在现实世界中使用它"来限定它,我肯定不会雇用他。让我用一句话来结束这个答案:
每次都胜过聪明。拉里·奥斯特曼
您的问题与using namespace std;
无关。问题是您将对 int (int&
) 的左值引用传递给在 int&
和 int*
上重载的函数。如果您删除了 using 指令,您将不会调用自己的交换;事实上,你的代码不会编译,因为C++不允许从指针到整数的隐式转换。为了使用你的函数,你必须调用它作为swap(&array[1], &array[4]);
现在,如果您更正了函数调用以反映这一点,则无论是否存在 using 指令,它都应该有效。然而,我建议不要这样做。std::swap
的语义是交换两个引用,而不是指针。重载语义不兼容的标准函数不仅会让熟悉标准库的人感到困惑,而且很可能会破坏在int*
上使用std::swap
的完全有效的代码。
你可能会想,"但这只有在他们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(例如,int
)选择用户定义的交换,同时仍然能够将std::swap
用于其他 T。
换句话说:始终提供swap
引用参数,并在需要交换模板化类型时使用作用域内声明。
- 即使没有调用这个递归函数,它是如何工作的?
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- 推理类型如何工作"auto"和按引用调用?
- 以下代码如何工作以每次为唯一调用堆栈唯一实例化模板函数?
- 递归函数调用在后台工作
- std::async 如何工作:为什么它会调用这么多次复制/移动?
- QLibrary 函数在第一次调用时工作缓慢
- 工作线程一直在等待,condition_variable甚至调用了notify_all
- 虚拟基类在内部如何工作?编译器如何解析对基方法的调用?
- 在新作用域中使用unique_lock是否等效于在使用共享资源的工作结束时解锁调用
- 从Excel VBA调用C++DLL只能从Visual Studio中的调试实例工作
- 异步操作的 Asio 处理程序在其同步对应项正常工作时不会调用
- 如何使功能"run"工作。程序在调用运行时退出
- 当在函数调用中递增值时,程序正常工作,但是如果我们在单独的行中增加值而不是呼叫函数,则会出现错误.为什么
- 在线程中调用线程会给我带来错误,如果我只调用该函数,则可以正常工作
- boost::asio 使用 post() 时没有调用处理程序,当直接调用函数时有效(io_context有工作)
- 为什么用未申报的变量工作调用函子
- 引用调用在 c++ 中如何工作?
- winsock连接调用崩溃如果多个线程运行,则在一个线程中正常工作
- C Google Mock -Expect_Call() - 期望在不直接调用时无法正常工作