2015-07-12 44 views
-5

我只是在研究C++类型,当时我只想着尝试下面的程序。C++隐式类型转换字符串 - > int?

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; 
    } 

我没想到会交换字符串,但它确实!为什么这个工作?虽然编译器提出了警告,但这不是一个错误!

+1

为了验证你的程序确实按照你的想法做了什么,使你的'swap'函数打印一条消息。 –

+0

要改善您的问题,请发布提供问题的实际代码。你显然省略了一些线,也许认为它们不重要。 –

+0

感谢您的反馈意见。这真的很有帮助。我没有预料到内置的交换功能会被调用。我按照@n.m的建议打印了一条消息。这证明我的交换没有被调用。我曾经使用过“使用命名空间标准”,这是这里的罪魁祸首。非常感谢!下次将包含完整的代码。对不起, –

回答

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。

因此,当您在std::string上调用函数swap时,它还会在std名称空间中查找候选项。并且由于std::swap可以应用于字符串,并且不会在您的全局名称空间中使用其他候选项(因为您的交换只能对整数进行操作),它将用于该调用。


正如我上面显示你可以让你的函数产生的调试输出或重新命名它很容易验证它不是你的函数被调用。

作为一个方面说明:假设有某种从字符串到int的隐式转换。你会得到两个临时工。然后你的交换函数会被调用(实际上不是,因为binding non const references to temporaries isn't allowed)和这些整数交换。接着?这对原始字符串没有任何影响。


最后,我不会将此代码计算为便携式。它只在头部字符串或iostream包含算法头部时编译,而这三者之一为字符串提供了std :: swap的特化。但是由于这个标准似乎没有保证,所以这个代码只有在你自己包含算法时才能可靠地工作。

+0

感谢@Daniel。这是非常丰富的文章! –

2

你的程序不能编译。我猜测,你实际上有以下几行,但没有张贴:

#include <iostream> 
#include <string> 
using namespace std; 

有一个标准模板std::swap。虽然这是#include <algorithm>,但任何标题都可能包含任何其他标题。所以即使你没有特别包括这个,它可能已经包含在内了。

因此,当您调用不合格的swap时,您的swapstd::swap都包含在重载解析中。 (即使您没有using namespace std;,由于ADL仍然搜索命名空间std,因为参数的类型为std::string,它在命名空间std中)。

为避免发生这种情况,您可以将swap放在命名的命名空间中,并使用限定名称(例如mystuff::swap(a, b);)。

相关问题