#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
using namespace std;
class Mystring
{
public:
Mystring(char * str =NULL);
Mystring(const Mystring & str);
Mystring & operator = (const Mystring & str);
void print();
~Mystring();
private:
char * data;
};
Mystring ::Mystring(const Mystring &str)
{
/* 这里出现了致命错误 导致我debug半天。。因为是复制构造函数 所以在对象创建的时候调用 这个时候data 不一定是NULL
但是肯定是没有给data执行过new一段空间的 所以下面 就出现了 释放本来没有开辟的资源
if(data!=NULL)
{
cout<<"data!=null"<<endl;
delete[] data;
}
*/
data =new char[strlen(str.data)+1];
strcpy(data,str.data);
}
Mystring::~Mystring()
{
if(data!=NULL)
delete[] data;
}
void Mystring::print()
{
cout<<data<<endl;
}
/*
//赋值函数的第一种写法 一般程序员写出这样的就可以了,一共四点注意的地方
//1 一定要注意返回引用 最后 return *this 这样可以连续赋值
//2 一定要记得传入的是常量引用 如果传入实例 从实参到形参要调用一次复制构造函数 效率差
Mystring& Mystring::operator =(const Mystring & str)
{
//3 判断传入的参数 和自己 是不是同一个。如果是的话 直接返回
if(this == &str)
return *this;
delete [] data;
data=NULL;//4 一定要记得释放掉原本自身资源后 给data 赋NULL
data=new char[strlen(str.data)+1] ;
strcpy(data,str.data);
return * this;
}
*/
//第二种高级写法 考虑安全性 异常等因素如果new 内存不足。怎么办
//简单的方法 先new 再delete 还有一种神方法 就是先创建一个临时变量 再交换这个临时变量和的data。
Mystring& Mystring::operator =(const Mystring & str)
{
if(this !=&str)//先判断是否是自身赋值 注意这里的{} 灰常重要啊。。
{
Mystring tmp(str);//建立一个临时对象 注意 一旦离开了右括号 这个 临时对象就被弄死了
char * t=data;//这个临时变量的data被交换了
data=tmp.data;
tmp.data=t;
}//离开这个括号后 临时变量被析够 但是因为两个data交换过 所以析够的其实是原来对象的空间
return * this;
}
Mystring::Mystring(char * str)
{
if(str==NULL)
{
data=NULL;//这一句非常重要啊 否则会乱码。
return ;
}
int len=strlen(str);
data=new char[len+1];
strcpy(data,str);
}
int main()
{
char STR[]="lovezyy";
Mystring stra(STR);
stra.print();
Mystring strb;
strb=stra;
strb.print();
return 0;
}