按照我正在阅读的外部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
3 来自哪里?
如果我输入:
MyString cMyName(“abc”);
它只返回My name is: abc
为什么 3 与Abder-Rahman
一起显示?
感谢。
答案 0 :(得分:2)
您在此处发布的代码与教程中的代码不同。它引入了至少两个错误:
m_pchString=new char(m_nLength);
这应该是:
m_pchString=new char[m_nLength];
第一个为一个字符分配一个缓冲区,并用m_nLength初始化它。
另一个错误:
delete m_pchString;
应该是:
delete[] m_pchString;
因为你分配了一个数组(好吧,在修复第一个错误之后,就是这样)。你在名字中得到“3”的原因是因为字符串中第一个字符的所有内容都位于不属于你的内存中,所以它被某些东西覆盖了。有时程序会崩溃,有时会打印出正确的结果。那是你的UB。
答案 1 :(得分:1)
在构造函数中,为内部指针分配内存时会出现错误:
m_pchString=new char(m_nLength);
表示分配单个字符并使用值m_nLength
初始化该字符。与:比较:
m_pchString=new char[m_nLength];
这意味着动态分配m_nLength
个字符而不执行任何初始化。同时,在处理数组时,需要将调用更改为delete
以在析构函数中使用delete []
:
delete [] m_pchString;
正如@sbi正确指出的那样,你应该始终遵循三者的规律:如果你需要提供一个析构函数,那么你还应该提供一个复制构造函数和赋值运算符。不这样做意味着您的对象可以使用隐式定义的赋值和复制构造版本进行复制,这些版本将复制指针,但不会复制内存。然后在某个时刻调用析构函数,调用析构函数的第二个副本将以未定义的行为结束,最有可能是分段错误。