为什么这个程序会交换值?

10
我有以下代码:
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <conio.h>
#include <cstring>
#include <iomanip>

void swap(long a, long b)
{
    long temp;

    temp=a;
    a=b;
    b=temp;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int x = 5, y = 3;
    cout << x ;
    cout << y << endl;

    swap(x, y);

    cout << x ;
    cout << y << endl;

    getch();
    return 0;
}

该程序输出:

5 3

3 5

该程序实际上交换了数值!为什么?因为swap()的参数不是指针或引用。

(我正在使用VS 2005)


基本上,这是 https://dev59.com/wnE85IYBdhLWcg3wkkbK#2712125 的一个副本,但除非你知道答案,否则你不会知道这一点。 - sbi
2个回答

37

你的swap函数根本没有被调用。

你所包含的标准库之一是引入了<utility>,它在std命名空间中声明了一个名为swap的函数模板。由于你使用了using namespace std;,所以这个swap函数被引入到全局命名空间中,并且被调用了。


为什么选择std::swap而不是你的swap函数?你的swap函数通过值传递了两个long类型的参数;要调用该函数,需要对每个int参数进行整数提升。

std::swap是一个函数模板。它接受两个T类型的引用,当该函数模板实例化为T = int时,两个参数都是精确匹配的。因此,在重载决议期间,std::swap比你的函数更匹配,因此被选中。


这就是using namespace std;是邪恶的并且应该避免使用的原因之一。如果你删除using指令,你的函数将是唯一可用的函数,并且将被调用。


7
你可以通过 ::swap(x, y) 调用 swap()。 - Zifei Tong

1

使用 long 代替 int

您当前的代码已经有了更好的匹配项,因此它避免了对 long 的隐式转换,并改为使用 STL 中内置的 swap

顺便提一下,在 D 语言中,可以使用重载集(也可以在这里)来解决这种歧义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接