可运行的总代码:
#pragma warning(disable:4996)
#include <string.h>
#include <cstdio>
#include <iostream>
//using std::cout;
//using std::cin;
//using std::endl;
using namespace std;
class CMyString
{
public:
CMyString();//无参构造函数
CMyString(const char* m_pDate);//有参构造函数
CMyString(const CMyString& str);//深拷贝
CMyString& operator=(const CMyString& str);//赋值运算符函数
~CMyString(void);//析构函数
void print() {
if (m_pDate) {
cout << m_pDate << endl;
}
}
void swap(CMyString& str) {
std::swap(m_pDate, str.m_pDate);
}
size_t length() const {
return strlen(m_pDate);
}
const char* c_str() const {
return m_pDate;
}
private:
char* m_pDate;
};
CMyString::CMyString()
:m_pDate(new char[1]())
{
cout << "CMyString()" << endl;
}
CMyString::CMyString(const char* pData)
:m_pDate(new char[strlen(pData) + 1]())
{
strcpy(m_pDate, pData);
cout << "CMyString(const char*)" << endl;
}
CMyString::CMyString(const CMyString& str)
:m_pDate(new char[str.length() + 1]())
{
strcpy(m_pDate, str.m_pDate);
cout << "CMyString(const CMyString&)" << endl;
}
//考察代码:赋值运算符函数
CMyString& CMyString::operator=(const CMyString& str)
{
if (this != &str) {
CMyString strTemp(str);
char* pTemp = strTemp.m_pDate;
strTemp.m_pDate = m_pDate;
m_pDate = pTemp;
}
return *this;
}
CMyString::~CMyString()
{
if (m_pDate) {
delete[] m_pDate;
m_pDate = nullptr;
}
cout << "~CMyString()" << endl;
}
void test0()
{
CMyString s1;
cout << 1;
s1.print();
CMyString s2 = "hello";
cout << 2;
s2.print();
CMyString s3(s2);
cout << 3;
s3.print();
CMyString s7, s8;
s7 = s8 = s3;//连续赋值
s7.print();
s8.print();
s3.print();
}
int main(void)
{
test0();
return 0;
}
运行结果:
CMyString()
1
CMyString(const char*)
2hello
CMyString(const CMyString&)
3hello
CMyString()
CMyString()
CMyString(const CMyString&)
~CMyString()
CMyString(const CMyString&)
~CMyString()
hello
hello
hello
~CMyString()
~CMyString()
~CMyString()
~CMyString()
~CMyString()
考察代码:
CMyString& CMyString::operator=(const CMyString& str)/*CMyString&:把返回值的类型声明为该类型的引用,只有返回一个引用,才可以允许连续赋值。CMyString& str:把传入的参数的类型声明为常量引用,形参到实参不会调用复制构造函数,提高代码效率。const:且在此函数里不会改变传入的实例的状态,因此加上const关键字。*/
{
if (this != &str) {/*需判断传入的参数str与当前的实例this是不是同个实例,如果是同一个,则不进行赋值操作,直接返回。因为当需判断传入的参数str与当前的实例this是同个实例,一但释放了自身this的内存,传入的参数str的内存也同时被释放掉了,因此找不到需要赋值的内容了*/
CMyString strTemp(str);/*创建一个临时变量strTemp,值为实例的值,strTemp的作用域只在if代码块里生效,除了if代码块,程序自动调用strTemp的析构函数,(strTemp指向的内存与str是一样的,)结果会把形参的实例所指向的内存释放掉*/
char* pTemp = strTemp.m_pDate;/*以下是交换临时变量实例strTemp与原来的实例this*/
strTemp.m_pDate = m_pDate;
m_pDate = pTemp;
}
return *this;//返回一个指针类型的变量
}
额外知识:
m_pDate=new char[strlen(str.m_pDate)+1];//这种方式用new分配内存,如果此时内存不足导致new char抛出异常,则m_pDate将是个空指针。
CMyString strTemp(str);//在构造函数里用new分配内存,(用str实例给当前实例this赋值),如果由于内存不足抛出诸如bad alloc等异常,抛出异常则不会修改当前实例的状态,当前实例状态还是有效的,保证了异常安全性。
delete []m_pDate;//在给当前实例分配新内存之前需释放自身已有的空间,否则程序将出现内存泄漏。
代码参考以往的csdn社区博客作出。