2015-07-12 74 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);)。

相關問題