实现自己的string类

一、关于等位拷贝

在代码中,sizeof(mystring) = 4字节,等位拷贝会把这四个字节等位拷贝过去。

它们指向同一段内存,到最后ms要析构,ms2也要析构,所以一段内存就会被析构两次,就是double free 

#ifndef STRING_H
#define STRING_H
#include <stdio.h>
#include <string.h>

class mystring
{
public:
    mystring(const char *p = NULL);//这里如果没有加NULL的话,定义mystring ms的时候会报错
    ~mystring();
    mystring(const mystring &another);
    mystring & operator=(const mystring & another);
    char* c_str();
private:
    char* _str;
};

#endif // MYSTRING_H

 

#include "mystring.h"

mystring::mystring(const char *p)
{
    if(p == NULL)
    {
        _str = new char[1];
        *_str = '\0';
    }
    else
    {
        int len = strlen(p);
        _str = new char[len + 1];
        strcpy(_str, p);
    }
}

mystring::~mystring()
{
    delete []_str;
}

char* mystring::c_str()
{
    return _str;
}


#if 0
1、格式 A(const A & another);
2、若不提供,系统会提供默认,一旦自定义,系统不再提供默认
3、系统提供的默认,是一种等位拷贝,也就是浅拷贝
4、浅拷贝,会导致,内存重析构。double free
5、在有些情况下(含有堆空间),要自实现拷贝构造,就是在拷贝构造函数里面再申请一段内存,然后在进行拷贝。


#endif
/*
mystring::mystring(const mystring & another)//默认拷贝函数
{
    _str = another._str;//在同类之间是没有隐私的

      class A
      {
       public:
            void func(const mystring & another)
            {
                p = another._str;//这种就绝对不可以,这两个类不一样
            }
      }
}
*/

mystring::mystring(const mystring & another)//自实现拷贝函数
{
    int len = strlen(another._str);
    _str = new char[len + 1];
    strcpy(_str, another._str);
}


#if 0
赋值运算符重载=
1、编译器提供默认(编译成功的原因),一旦自定义,系统不再提供默认
2、默认赋值运算符重载也是一种等位赋值,浅赋值。
3、浅赋值有可能会导致自身内存泄露,内存发生重析构,还有可能导致自赋值问题。
4、
#endif


mystring& mystring::operator=(const mystring& another)
{
    if(this == &another)
    {
        return *this;
    }
    delete []this->_str;
    int len = strlen(another._str);
    this->_str = new char[len + 1];
    strcpy(this->_str, another._str);
    return *this;   //return的目的是为了实现连等式
}
#include <iostream>
#include "mystring.h"

using namespace std;

int main()
{
    string s; //char *p = ""
    string s2("china");//char *p = "china"

    cout<<s.c_str(); //string char*
    cout<<s2.c_str()<<endl;

    string s3(s2);//用一个对象生成另外一个对象,利用了拷贝构造器
                  //拷贝构造器:由已存在的对象,创建新的对象,也就是说新的对象,不由构造器来构造,而是由拷贝构造器
                  //来完成。
    cout<<s3<<endl;

    string s4 = s3;//这个操作看上去像一种复制行为,但它的本质还是拷贝构造,用一个已有的对象,完成一个对象从无到有
                   //的创建过程
    cout<<s4<<endl;

    string s5;
    s5 = s4;
    cout<<s5.c_str()<<endl;
    
    string s6;
    s6 = s5 = s4;
    cout<<s6.c_str()<<endl;

    cout<<"************************************************************"<<endl;
    mystring ms;
    mystring ms2("canada");
    cout<<ms.c_str();
    cout<<ms2.c_str()<<endl;

    mystring ms3(ms2);    //没有进行任何改动竟然也可以,我觉得很不可思议,因为ms2是一个类,但是竟然可以作为参数
                          //传到ms3的构造函数中
                          //其实这里ms3没有调用有参或无参的构造器,而是调用了默认的拷贝构造器,以前传进来的是NULL
                          //或char*
    cout<<ms3.c_str()<<endl;

    mystring ms4 = ms3;
    cout<<ms4.c_str()<<endl;

    mystring ms5;
    ms5 = ms3;    //赋值运算符重载,系统也有默认
                  //赋值运算符重载时机:用一个已有对象,给另外一个已有对象赋值,两个对象均已创建结束,发生的赋值行为
                  //ms5.operator =(ms3);
    cout<<ms5.c_str()<<endl;
    
   mystring ms6;
   ms6 = ms5 = ms4;//ms6.operator =(ms5.operator =(ms4))
   cout<<ms6.c_str()<<endl;

    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值