2012-10-15 29 views
3

當我嘗試編譯下面的源代碼時,出現以下錯誤。任何人都可以描述爲什麼這個錯誤存在,我怎麼能解決它?帶錯誤的引用變量,必須在構造函數庫/成員初始化程序中初始化

錯誤1錯誤C2758: 'A :: S_':必須構造鹼/成員初始

#include <iostream> 
#include <string> 

using namespace std; 

class A 
{ 
public: 
    A(string& s) : s_(s) { cout << "A::ctor" << endl; } 
    A(const A& rhs)  { cout << "A::copy" << endl; } 
    ~A()     { cout << "A::dtor" << endl; } 

    A& operator=(const A& rhs) { cout << "A::copyassign" << endl; } 

private: 
    string& s_;  
}; 

int main() 
{ 

    return 0; 
} 
+1

當你有一個引用成員時,你不能真正擁有一個語義上有效的賦值運算符。您不能將其重新分配給不同的字符串。它只會修改被引用的原始字符串。 –

回答

7

首先,你A::s_是一個std::string參考;這意味着它引用了某個地方必須存在的東西。

由於他引用類型的,而事實上,引用必須在他們所創建的那一刻被初始化,你必須在所有的A構造函數初始化A::s_(由其他用戶指出):

class A 
{ 
public: 
    A(string& s) : s_(s) 
    { cout << "A::ctor" << endl; } 

    A(const A& rhs) : s_(rhs.s_) // <-- here too!! 
    { cout << "A::copy" << endl; } 

    ~A() 
    { cout << "A::dtor" << endl; } 

    A& operator=(const A& rhs) 
    { cout << "A::copyassign" << endl; } 

private: 
    string& s_;  
}; 

現在回到我剛纔提到的第一件事。在A::s_必須參考的東西存在,所以你必須知道的一些事情,看看下面的代碼:

int main() 
{ 
    // New A instance: 
    A a("hello world"); 

    return 0; 
} 

構建這個A情況下,我們要提供一個const char[12]值,這個值暫時std::string被創建並被賦予A::A(string& s)構造函數。 A::s_在構造函數結束後引用的位置?創建臨時std::string會發生什麼?它的使用壽命是延長還是隻有A構造函數結束時死亡?你確定參考是你需要的嗎?

std::string s("hello world"); 

int main() 
{ 
    // New A instance: 
    A a(s); 

    return 0; 
} 

通過上面的代碼,創建一個新的A實例調用相同A::A(string& s)構造函數,但提供的字符串趴在全球範圍內,所以也沒有被破壞,A::s_a實例將引用一個有效的字符串的所有生命週期,但真正的威脅是拷貝構造函數:

std::string s("hello world"); 

int main() 
{ 
    A a(s); // a.s_ references the global s. 
    A b(a); // b.s_ references the a.s_ that references the global s. 

    return 0; 
} 

複製的對象值將引用給定對象的std::string!那是你要的嗎?

+0

非常感謝您的詳細描述。 – Number42

+1

我只想指出,由於臨時對象不能綁定到非常量引用,因此您無法首先將「hello world」傳遞給它(即編譯器錯誤)。 – chris

+0

@chris [它的工作](http://ideone.com/SJds5)對我來說。在'A a(「hello world」)調用中創建的臨時對象被綁定到'a.s_'引用。 –

2

你的拷貝構造從未初始化參考被初始化。請確保它:

A(const A &rhs) : s_(rhs.s_) {cout << "A::copy" << endl;} 
0
string& s_; 

這是一個全球化志願服務青年變量。當對象被分配時它應該有一個值,因爲這是對象的一部分,這就是爲什麼應該使用構造函數的初始化列表來初始化這個屬性。

如果您不需要有這個屬性附加傷害,如對象的一部分,你可以使用一個指針,而不是全球化志願服務青年:

string* s_; 
相關問題