2011-01-23 146 views
-5

以下是我正在閱讀的外部C++學習資源的示例。C++ - 奇怪的輸出

主要內容如下:

#include <iostream> 
#include <cstring> 
class MyString 
{ 
private: 
char *m_pchString; 
int m_nLength; 

public: 
MyString(const char *pchString="") 
{ 
//find the length of the string 
//plus "1" for a terminator 
m_nLength=strlen(pchString)+1; 
//allocate a buffer equal to this length 
m_pchString=new char(m_nLength); 
//copy the parameter into our internal buffer 
strncpy(m_pchString,pchString,m_nLength); 
//make sure the string is terminated 
m_pchString[m_nLength-1]='\0'; 
} 

~MyString() //destructor 
{ 
//deallocate buffer 
delete m_pchString; 
//set m_pchString to null just in case 
//m_pchString=0; 
} 

char* GetString() 
{ 
return m_pchString; 
} 

int GetLength() 
{ 
return m_nLength; 
} 
}; 

int main() 
{ 
MyString cMyName("Abder-Rahman"); 
std::cout<<"My name is: "<<cMyName.GetString()<<std::endl; 
return 0; 
} //cMyName destructor is called here 

輸出是:My name is: Abder-Rahman3

哪兒了來自?

如果鍵入:

MyString cMyName("abc");

它只是簡單地返回My name is: abc

爲什麼出現與Abder-Rahman

謝謝。

+18

老兄!你會停止廣告learncpp.com。去拿一本教科書。 – Neo 2011-01-23 13:53:43

回答

2

您在此處發佈的代碼與本教程中的代碼不同。它引入了至少兩個錯誤:

m_pchString=new char(m_nLength); 

這應該是:

m_pchString=new char[m_nLength]; 

第一個分配一個緩衝區一個字符,與m_nLength初始化。

另一個錯誤:

delete m_pchString; 

它應該是:

delete[] m_pchString; 

因爲你分配一個數組(當然,你固定第一錯誤之後,這是)。你在名字中得到「3」的原因是因爲經過字符串中第一個字符的所有東西都位於內存中,它並不屬於你,所以它被某些東西覆蓋。有時程序會崩潰,有時會打印正確的結果。這對你來說是UB。

1

在構造中,內部指針分配內存時,有一個錯誤:

m_pchString=new char(m_nLength); 

手段分配單個字符和初始化該字符與值m_nLength。比較:

m_pchString=new char[m_nLength]; 

這意味着動態分配m_nLength字符而不執行任何初始化。同時,您需要更改調用delete在析構函數使用delete [],因爲你面對的陣列,而不是單一的元素:

delete [] m_pchString; 

由於@sbi正確地指出,你應該始終遵循三者的規律:如果你需要提供一個析構函數,那麼你還應該提供一個拷貝構造函數和賦值操作符。如果不這樣做,意味着您的對象可以使用隱式定義的賦值和複製構造版本進行復制,該版本將複製指針而不是內存。然後析構函數會在某個時刻被調用,而第二個調用析構函數的副本將以未定義的行爲和最可能的分段錯誤結束。