01

xiaoxiao2021-02-28  25

代码出自剑指offer,自己做了详细的注释,代码如下: #include<cstring> #include<cstdio> #include<iostream> using namespace std; class CMyString { public: CMyString(const char* pData = nullptr);//构造函数 CMyString(const CMyString& str);//构造函数 ~CMyString(void);//析构函数 CMyString& operator = (const CMyString& str);//算术符重载 void Print(); private: char* m_pData; }; CMyString::CMyString(const char *pData)//传一个字符串进去 { if (pData == nullptr) { m_pData = new char[1]; //开辟空间大小为1 m_pData[0] = '\0'; } else { int length = strlen(pData); m_pData = new char[length + 1]; strcpy_s(m_pData, length + 1, pData);//因为要考虑\0占据一个单位,所以是length + 1,这里是把pData赋值给m_pData的意思 } } CMyString::CMyString(const CMyString &str)//传一个对象进去 { int length = strlen(str.m_pData); m_pData = new char[length + 1]; strcpy_s(m_pData, length + 1, str.m_pData); } CMyString::~CMyString()//析构函数 { delete[] m_pData; } // 重载 + 运算符,用于把两个 Box 对象相加 //Box operator + (const Box& b) CMyString& CMyString::operator = (const CMyString& str)//算术符号重载,返回类型是对象的引用,::operator =表示重载函数在类外面被调用,(const CMyString& str)表示被重载的=右侧的的数据类型是什么 { if (&str != this)//这个意思是,如果当前对象和原有的对象不是同一个的话 { CMyString strTemp(str); char* pTemp = strTemp.m_pData; strTemp.m_pData = m_pData; m_pData = pTemp; } //假设我们的算术重载最终是想要执行CMyString xxx=y这样的操作。 //注意,这里离开if以后,strTemp会被自动析构,而pTemp也会被删除,因为它们都是局部变量 //这里之所以这么操作,是因为,如果直接把str赋值给this的话,可能需要为m_pData开辟的空间不够了,这个时候 //m_pData就会得到一个空指针,最终在cout输出空指针时就会挂掉。 //挂掉只是其次,原来的CMyString数据可能也会被毁掉,因为可能执行了CMyString xxx=NUll这样的语句效果 //为了不毁掉原来的CMyString xxx中的内容,先把str的内容拷贝到一个临时的对象CMyString strTemp中 //那么此时,即使空间不够程序挂掉,原来的CMyString xxx的数据也不会被毁掉。 //也就是说空指针进行赋值是不会导致崩溃的,但是输出空指针是会导致程序崩溃的 cout <<this << endl; return *this;//返回当前对象的引用,如果是return this,那么就返回当前对象的地址 }//这里之所以是返回*this,是因为重载本身就是在处理对象,或者说,是在调整对象的属性,所以调整前和调整后,都是对象进,对象出。 // ====================测试代码==================== void CMyString::Print() { printf("%s", m_pData); } void Test1() { printf("Test1 begins:\n"); const char* text = "Hello world"; //不可更改的字符串指针 CMyString str1(text);//利用构造函数进行初始化 CMyString str2; str2 = str1;//对象赋值 printf("The expected result is: %s.\n", text); printf("The actual result is: "); str2.Print(); printf(".\n"); } // 赋值给自己 void Test2() { printf("Test2 begins:\n"); const char* text = "Hello world"; CMyString str1(text); str1 = str1; printf("The expected result is: %s.\n", text); printf("The actual result is: "); str1.Print(); printf(".\n"); } // 连续赋值 void Test3() { printf("Test3 begins:\n"); const char* text = "Hello world"; CMyString str1(text); CMyString str2, str3; str3 = str2 = str1; printf("The expected result is: %s.\n", text); printf("The actual result is: "); str2.Print(); printf(".\n"); printf("The expected result is: %s.\n", text); printf("The actual result is: "); str3.Print(); printf(".\n"); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); cin.get(); cin.get(); return 0; }

上图是代码中的异常安全处理部分的数据流图

关于空指针导致崩溃问题可以参考点击打开链接

转载请注明原文地址: https://www.6miu.com/read-2630013.html

最新回复(0)