2017-03-07 86 views
3

我所試圖做的是,讓一個指針,引用或恆定參考與這些setter函數傳遞:函數調用模糊性指針,引用和恆定的參考參數

class A{ 
    std::string * p; 
    std::string st; 

    public: 
    A():p(0) 
    {} 
    A& setS(const std::string& s){ 
     std::cout<<"called with const std::string&\n"; 
     st = s; 
     p = &st; 
     return *this; 
    } 
    A& setS(std::string& s) { 
     std::cout<<"called with std::string&\n"; 
     p = &s; 
     return *this; 
    } 
    A& setS(std::string* s) { 
     std::cout<<"called with std::string*\n"; 
     p = s; 
     return *this; 
    } 
}; 

int main(){ 
    std::string s; 
    A a; 
    a.setS(std::move(s)) //const std::string& 
    .setS("")   //const std::string& 
    .setS(s)   //std::string& 
    .setS(0);   //std::string* 
    //if std::string* version is not defined, 
    //setS(0) calls the const std::string& version and throws exception 
    return 0; 
} 

但我已經看到, ,如果指針版本不存在,則setS(0)調用setS()函數的const std::string&版本。

指針和參考版本之間或任何其他問題之間有任何歧義嗎?它是否定義清晰,並且預計在所有編譯器中都以相同的方式工作?

+0

即時通訊假設發生了什麼是您可以從(空)指針創建一個字符串,並且該臨時將綁定到一個const引用。雖然在這種情況下不受歡迎,但這對我來說似乎是「正常行爲」。 – Borgleader

回答

3

沒有歧義。如果在過載集中有A& setS(std::string* s),則setS(0)將調用指針版本,而0是空指針。這將是相當於setS(nullptr)

A& setS(std::string* s)不設置過載,則編譯器會檢查是否有一種方法,它可以從0構建一個臨時字符串,然後傳遞到A& setS(const std::string& s)因爲const&可以綁定到一個暫時的。 std::string可以由單個指針構造而成,並且再次0它作爲空指針行走。所以你得到一個臨時的空指針std::string構造成傳遞給const&函數。

雖然這是未定義的行爲。 std::string的構造函數要求傳遞給它的指針是一個以null結尾的c字符串。如果不是,那麼行爲是不確定的。

0

當您刪除setS函數的指針超載時,您調用const std::string&版本的原因是因爲one of the std::string constructors

basic_string(const CharT* s, 
       const Allocator& alloc = Allocator()); 

所以0被視爲NULL,並解釋爲const char*,從該std::string可以構造。 const&能夠延長左值的壽命,以便它可以傳遞到setS的超載。

+1

'0'並不真正被當作NULL來處理,因爲'NULL'通常只擴展爲'0'。不過,它被視爲空指針。 – Angew