C++学习day11之string自实现

#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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值