我只是在研究c ++类型,当时我只是想尝试下面的程序。
void swap(int& a, int& b){
int temp = a;
a = b;
b = temp;
}
int main(){
string a{"sssss"}, b{"ddddd"};
swap(a,b); //this should not work!! but it does
cout << a << ' '<<b <<endl;
return 0;
}
我没想到要交换字符串,但它确实如此!这为什么有效?虽然编译器会发出警告,但这不是错误!
答案 0 :(得分:2)
您的程序无法编译。我猜你实际上有以下几行但未能发布它们:
#include <iostream>
#include <string>
using namespace std;
有一个标准模板std::swap
。虽然这在#include <algorithm>
中,但任何标头都可以包含任何其他标头。所以,即使你没有特别说明这一点,它也可能已被包括在内。
因此,当您拨打不合格的swap
时,您的swap
和std::swap
都会包含在重载解析中。 (即使您没有using namespace std;
,仍然会因为ADL而搜索名称空间std
,因为参数的类型为std::string
,位于名称空间std中。
为避免发生这种情况,您可以将swap
放入命名的命名空间,并使用限定名称(例如mystuff::swap(a, b);
)。
答案 1 :(得分:1)
// Assuming the following:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
// or even using namespace std, though this
// would make std::swap a candidate even
// without ADL
// renaming shows that it's not this function
// that gets called ...
void myswap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
// printing some output also reveals what's going on
}
int main() {
string a{"sssss"}, b{"ddddd"};
swap(a,b); // this is not calling your swap!
// myswap(a,b) produces the error you expected
cout << a << ' '<< b <<endl;
return 0;
}
它没有调用你的交换功能。命名空间是一种接口,因此当一个声明自由函数与它们所操作的数据类型在同一个命名空间中时,那么在没有正确的命名空间限定的情况下调用它们将起作用。
这称为“参数依赖名称查找”或ADL。
因此,当您在swap
上调用函数std::string
时,它还会在std
命名空间中查找候选项。因为有std::swap
,它可以应用于字符串而不是全局命名空间中的其他候选者(因为你的交换仅对整数进行操作),它会将它用于调用。
如上所示,您可以使您的函数生成调试输出或重命名它以轻松验证它不是您调用的函数。
作为旁注:假设存在某种从字符串到int的隐式转换。然后你会得到两个临时工。然后你的交换函数将被调用(实际上不是,因为binding non const references to temporaries isn't allowed)并且交换了这些整数。然后?这对原始字符串没有任何影响。
最后,我不认为这段代码是可移植的。它只在头字符串或iostream包含算法头时才编译,这三个中的一个为字符串提供了std :: swap的特化。但是,由于标准似乎没有保证这一点,因此只有在自己包含算法时,此代码才能可靠地工作。