#include<iostream>
#include<cstring>
using namespace std;
class String
{
public:
String(const char *p=NULL)
{
if(p==NULL)
{
str=new char;
*str='\0';
}
else
{
int len=strlen(p);
str=new char[len+1];
strcpy(str,p);
}
}
//拷贝构造器
//1.格式 A(const A & anoher);
//2.若不提供,系统会提供默认的。一旦自定义,系统不再提供默认。
//3.系统提供的默认是一种等位拷贝,也就是江湖上说的,浅浅的拷贝。
//浅浅的拷贝就是指的是,本类里面有个str,你传进来的那个String
//也有个str,这里你可以看到他会把这四个字节完全的拷贝过去
//比如你P里面的str的值是0x12abcdef 那么我本类里面str的值也是0x12abcdef
//那么就发现指向了同一段内存,那么问题来了,我虚构的时候释放了两次。
//4.浅拷贝,会导致,内存重析构。就会出现double free这种东西
//在有些情况下(含有堆空间的时候),要自实现拷贝构造。
//
String(const String & p)
{
//这里不奇怪吗,str是私有成员,为什么你可以访问到
//所以这里说明一点,在同类之间是没有隐私的。
int len;
len=strlen(p.str);
str=new char[len+1];
strcpy(str,p.str);
}
~String()
{
delete str;
}
char* c_str();
//赋值运算符重载
//发生的时机
//用一个已有对象,给另外一个已有对象赋值,两个对象均已创建结束后
//发生的赋值行为。
//1.系统提供默认(编译成功的原因),编译器提供默认的也是一种等位赋值。
//所以也是一种浅拷贝。
//2.浅赋值可能遇见下面的问题。
// 2.1内存泄漏。那这个例子来说,你生成一个对象,那么
// 你虚构函数中就申请了一段内存
// 然后你浅拷贝。你的那段内存就泄漏了。
// 2.2 double free
// 2.3自己赋值给自己
//一旦自定义,系统不再提供。
//格式非常固定
//类名
//{
// 类名& operator=(const 类名 &原对象)
// 拷贝体
//}
String & operator=(const String & src)
{
//避免自己赋值给自己,因为你那样第一个就把自己的那段空间给干了
if(this == &src)
return *this;
delete this->str;
int len = strlen(src.str);
this->str=new char[len+1];
strcpy(this->str,src.str);
return *this;
}
String operator+(const String &src)
{
String dst(*this);
if(src.str==NULL)
{
return dst;
}
else
{
delete dst.str;
dst.str=new char[strlen(this->str)+strlen(src.str)+1];
strcpy(dst.str,this->str);
strcpy(dst.str+strlen(this->str),src.str);
return dst;
}
}
char &operator[](int dex)
{
return this->str[dex];
}
char at(int dex)
{
return this->str[dex];
}
void swap(String &p)
{
char *temp=p.str;
p.str=this->str;
this->str=temp;
}
private:
char *str;
};
char *String::c_str()
{
return str;
}
int main()
{
String str("hello");
//用一个对象生成另外一个对象,拷贝构造器
//由已经存在的对象,创建新对象,也就是说新对象
//不由构造器来构造。而是由拷贝构造器来完成。
String str1(str);
//这个看起来是赋值行为,但是本质也是拷贝构造。用已有的对象完成对一个
//对象从无到有的创建过程
String str2=str1;
//char * &p=q;
//str.swap(q);
String str3;
//能编译通过说明存在赋值运算符重载的。
//学之前,我们先学this指针
//系统在创建对象时,默认生成的指向当前对象的指针。这样做的目的
//就是为了带来方便,看this.c
str3=str2;
String str4("gggggggggggg");
str3.swap(str4);
//这里可以使用str6=str5=str4;
//这里就相当于str6.operator=(str5.operator=(str4))
cout<<str3.c_str()<<endl;
/*
*标准的string
*还有下面这些功能
*string str;
*这两个不一样的地方在于 str[2]是可以赋值的,比如str[2]='a';
*str[2];
*
*str.at(2)
*
*/
String a("aa");
String b("bb");
String d("ccdd");
String c;
//String c=a+b;
a="cccc";
a[2]='1';
char ch=a.at(2);
c=c+d;
cout<<a.c_str()<<endl;
cout<<c.c_str()<<endl;
cout<<ch<<endl;
return 0;
}
C++学习day11之string自实现
最新推荐文章于 2019-10-26 14:27:57 发布