2011-01-23 151 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正确地指出,你应该始终遵循三者的规律:如果你需要提供一个析构函数,那么你还应该提供一个拷贝构造函数和赋值操作符。如果不这样做,意味着您的对象可以使用隐式定义的赋值和复制构造版本进行复制,该版本将复制指针而不是内存。然后析构函数会在某个时刻被调用,而第二个调用析构函数的副本将以未定义的行为和最可能的分段错误结束。