2012-07-25 51 views
2

我有以下代碼:爲什麼使用字符串的複製構造函數?

class TestClass 
{ 
public: 
    TestClass(){}; 

    std::string GetTestString() 
    { 
    return (mTestString); 
    } 
    void SetTestString(const std::string& rTestString) 
    { 
    mTestString = rTestString; 
    } 

private: 
    std::string mTestString; 
}; 

TestClass* pGlobalVar; 

void SomeFunction(TestClass MyClass) 
{ 
    pGlobalVar->SetTestString("cba"); 
    std::cout << "Changed string: " << pGlobalVar->GetTestString() << std::endl; 
    std::cout << "Copied string: " << MyClass.GetTestString() << std::endl; 

} 

int main() 
{ 
    pGlobalVar = new TestClass(); 
    pGlobalVar->SetTestString("abc"); 
    std::cout << "Original string: " << pGlobalVar->GetTestString() << std::endl; 
    SomeFunction(*pGlobalVar); 
    delete (pGlobalVar); 
} 

此輸出以下:

Original string: abc 
Changed string: cba 
Copied string: abc 

,因爲我沒有定義我的類定義拷貝構造函數,我希望一個單位的副本將作出,包括std::string中的指針。顯然,雖然使用std::string拷貝構造函數,但由於對原始字符串的更改不會更改副本。

任何人都可以向我解釋爲什麼它沒有製作平面複製?

我在Linux上使用GCC 4.4.6。

+1

'std :: string'被設計成(至少就複製而言)它的行爲類似於int。如果成員'mTestString'的類型爲'int',那麼'pGlobalVar-> mTestString'不會被修改爲調用'SomeFunction'。按照設計,'std :: string'也是如此。這是C++非常理想的特性。 – 2012-07-25 08:47:39

回答

5

,因爲我沒有定義我的課拷貝構造函數,我希望一個單位的副本會作出

既然你沒有定義拷貝構造函數,C++爲你做。

自動生成的拷貝構造函數調用其所有成員變量(如果它們有一個)的構造函數。

類似地,自動生成的構造函數調用其所有成員的構造函數,並且析構函數調用其所有成員的析構函數。

+0

嚴格來說,所有的類都聲明瞭一個拷貝構造函數。具有非POD成員的類型不是聲明或定義該構造函數的先決條件。 (你看起來像是這樣,但也許這不是你的意圖。) – 2012-07-25 08:56:47

+0

@Luc我沒有意識到這一點。你能否引用標準中的相關段落?畢竟,POD類沒有正規的構造函數,只有初始化器。 – 2012-07-25 09:03:23

+1

12.8複製和移動類對象[class.copy]第7段:「如果類定義沒有明確聲明覆制構造函數,則隱式聲明它。[...]」你可能想到的是一個特殊的成員可能是微不足道的,例如在'struct foo {int i; }'。(仍然允許編寫static_cast (&foo :: operator =)'然而(第12節第2段) - 很難說沒有複製賦值運算符。 – 2012-07-25 09:13:23

5

因爲我沒有爲我的類定義一個拷貝構造函數,所以我希望能夠製作一個平面拷貝,包括std :: string中的指針。

不,隱式生成的拷貝構造函數會使用它的拷貝構造函數複製每個數據成員(和基礎子對象)(如果它有一個拷貝構造函數的話)。

任何人都可以向我解釋爲什麼它沒有平面複製?

因爲那樣會很糟糕。一個類定義了一個複製構造函數,因爲它必須以某種方式複製;在std::string的情況下,它必須創建一個新的緩衝區。如果新字符串只保存了另一個指針的副本,那麼兩者都會認爲它們擁有相同的緩衝區,並且兩者都會在銷燬它們時嘗試釋放它。

相關問題