/* 注意:环境是在 VS 2019 在 <string.h> 里的 strcpy 被认为不安全,需要使用 strcpy_s strcpy_s 的用法: errno_t strcpy_s(char* dest, strlen(dest), const char* source); errno_t 是一个 int 的别名。*/#include <iostream>#include <string>#include <string.h>using namespace std;class CMyString {public: // 类的常见函数 // 0. 构造函数 // 1. 拷贝构造函数 // 2. 赋值构造函数 // 3. 析构函数 CMyString(const char* pData = nullptr); CMyString(const CMyString& str); CMyString& operator=(const CMyString& str); ~CMyString(void); const char* get_mData(void) const;private: char* m_pData;};inlineCMyString::CMyString(const char* pData) { if (pData) { // 获取需要赋值的字符串长度 m_pData = new char[strlen(pData) + 1]; // 使用 strcpy 将 pData 的内容赋值给m_pData strcpy_s(m_pData, strlen(pData) + 1, pData); // 注意:如果直接将 pData 的地址赋给 m_pData, // 则函数调用完毕,pData 的内容会被被回收,m_pData 也就指向了空。 // m_pData = pData; } else { // 关键: // 空字符串是一个 C 语言的数组,末位是 '\0',不并入数组的长度 m_pData = new char[1]; *m_pData = '\0'; }}inline CMyString::~CMyString(void) { cout << "delete [] members of " << this << endl; delete[] m_pData;}inlineCMyString::CMyString(const CMyString& str) { // 不管原字符串是否为空,都取其原长度 +1 的字符串。 m_pData = new char[strlen(str.get_mData()) + 1]; strcpy_s(m_pData, strlen(str.get_mData()) + 1, str.get_mData());}inlineCMyString& CMyString::operator=(const CMyString& str) { // 如果赋值的是同一个对象 if (this == &str) { return *this; } else { delete[] m_pData; m_pData = new char[strlen(str.m_pData) + 1]; strcpy_s(m_pData, strlen(str.m_pData) + 1, str.get_mData()); return *this; }}inlineconst char* CMyString::get_mData(void) const { return m_pData;}int main() { // 等号右边的值是 const char* // 等号左边的值是 char* // 类型不匹配 // char* test_str1 = "I am back."; const char* test_str2 = "test_2"; CMyString test1("test1"); cout << test1.get_mData() << endl; // 构造函数 CMyString test2(test_str2); cout << test2.get_mData() << endl; // 赋值构造函数 CMyString test3 = test2 = test1 = test2; // 三个实例的地址均不一样 cout << test2.get_mData() << endl; //cout << &test3 << endl; cout << &test1 << endl; cout << &test2 << endl; cout << &test3 << endl; return EXIT_SUCCESS;}