一刷剑指offer笔记(1)——赋值运算符函数

作为一只小白,编程能力差到爆炸,故决定从现在开始拜读《剑指offer》,此为一刷笔记。说实话,我觉着我这种垃圾水平,至少得多刷几次才能有一丢丢进步,究竟能刷多少遍还请拭目以待。

好的,其实虽然很不好意思,但是我看到赋值运算符的时候愣了一会儿,后来才反应过来就是“=”。

接着看了一下声明,完球了,两年前学的C++忘光光了,脑子里都是问题:

为啥要const类型?“~”是啥意思??

啊啊啊啊啊,为啥要这样声明啊啊啊啊????

罪恶啊罪恶,对不起C++老师!

认真思考了一下,结合书上给出的四个点,渐渐懂了一些。

首先,第一个点,返回类型得是类引用,不能是void,对应一下第三条~Cmystring(void),如果是void就调用了析构函数,就是扫尾清理,释放内存空间。

再看第二个点,传入的要是类引用,而且状态不会发生改变,所以引用参数加上const关键字,对应第二条。

接着第三个点和第四个点,是否释放内存,这个需要我们实现。

继续往下看,看到适用于初级程序员的解法,对应一下四个点来看看~~

实在不好意思,看了几遍才看懂,把博主自己的理解写在了下面,看来路还很长。。。

//满足返回值类型声明为该类类型的引用
//在C++中“::”为域操作符,即定义了一个在CMyString类里的成员函数
//“operator=”为等号重载标志,相当于一个函数
//(const CMyString &str)表示该成员函数的参数为类类型的引用
CMyString& CMyString::operator =(const CMyString &str)
{    
    //对应第四点,判断传入的参数是否与当前的实例(*this)相同,如果相同,直接返回
    if(this== &str)
        return *this;
    //释放实例m_pData的内存,突然有点迷,m_pData是啥子???接着往下看。
    delete []m_pData;
    m_pData=NULL;
    //给m_pData分配内存,分配多少呢?就和传入参数str中的m_pData大小一样。到这里就懂了m_pData的含义。就是该类的”值“,赋值的”值“。注意,这里埋下了安全的隐患!!
    m_pData=new char[strlen(str.m_pData)+1];
    //验证上面猜想的正确性,strcpy复制了~~
    strcpy(m_pData,str.m_pData);
    return *this;//返回值类型为类类型的引用。
}

继续往下,看到作为一名高级程序员的解法,要考虑异常安全性。

emmmm,看到这里,不由得想问,异常安全性是个啥?

不由自主联想到了java里的try、throw and catch,哈哈哈哈

正常的解释来了!!

异常安全的代码,满足两个条件:

1、异常中立性:当代码引发异常时,这个异常能够保持原样传递到外层调用代码

2、异常安全性:抛出异常后,资源不泄露,数据不恶化(eg:正常指针变野指针,所谓的野指针就是指针在首次使用之前没有初始化)

3、少try catch,会很丑。。。

实现异常安全性的方法:

1、先用new分配新内容再用delete释放已有的内容,但存在局限性,即只在分配内容成功之后再释放原来的内容,但是当内存分配失败时,CMyString的实例不会被修改。

2、先创建一个临时实例,再交换临时实例和原来的实例,如下代码

CMyString& CMyString::operator=(const CMyString &str)
{
    if(this!=&str)    
    {
        //创建临时实例strTemp
        CMyString strTemp(str);
        //将临时实例的m_pData赋值给变量pTemp
        char* pTemp=strTemp.m_pData;
        //把pTemp与实例自身的m_pData进行交换
        m_pData=pTemp;
    }
    //由于strTemp为局部变量,现在已经出了作用域,自动调用析构函数,释放临时变量strTemp.m_pData的内存
    return *this;
}

下面给出完整解题代码!!!

#include <iostream>
#include <cstdlib>
#include <cstring>

using namespace std;
class CMyString
{
public:
    //构造函数
    CMyString(char* pData=NULL);
    CMyString(const CMyString& str);
    //析构函数
    ~CMyString(void);
    //运算符重载
    CMyString& operator=(const CMyString& str);
    //输出函数
    void print();
private:
    char* m_pData;
};

CMyString::CMyString(char* pData)
{
    if(pData==NULL)
    {
        m_pData=new char[1];
        m_pData[0]='\0';
    }
    else
    {
        int length=strlen(pData);
        m_pData=new char[length+1];
        strcpy(m_pData,pData);
    }
}

CMyString::CMyString(const CMyString &str)
{
    int length=strlen(str.m_pData);
    m_pData=new char[length+1];
    strcpy(m_pData,str.m_pData);
}

CMyString::~CMyString()
{
    delete[] m_pData;
}

CMyString& CMyString::operator=(const CMyString& str)
{
    if(this==&str)
        return *this;
    delete[] m_pData;
    m_pData=new char[strlen(str.m_pData)+1];
    strcpy(m_pData,str.m_pData);
    return *this;
}

void CMyString::print()
{
    cout<<m_pData<<endl;
}

//一般情况下的测试
void Test_1()
{
    cout<<"Test1 begins:"<<endl;
    char* text="hello world!";
    CMyString str1(text);
    CMyString str2;
    str2=str1;
    cout<<"Expected result: "<<text<<endl;
    cout<<"Actual result: ";
    str2.print();
}

//自己给自己赋值的测试
void Test_2()
{
    cout<<"Test2 begins:"<<endl;
    char* text="hello world!";
    CMyString str1(text);
    str1=str1;
    cout<<"Expected result: "<<text<<endl;
    cout<<"Actual result: ";
    str1.print();
}

//连续赋值的测试
void Test_3()
{
    cout<<"Test3 begins:"<<endl;
    char* text="hello world!";
    CMyString str1(text);
    CMyString str2,str3;
    str3=str2=str1;
    cout<<"Expected result: "<<text<<endl;
    cout<<"Actual result: ";
    str2.print();
    cout<<"Expected result: "<<text<<endl;
    cout<<"Actual result: ";
    str3.print();
}

int main()
{
    Test_1();
    cout<<"############################"<<endl;
    Test_2();
    cout<<"############################"<<endl;
    Test_3();
}

贴出在codeblocks 17.0下的测试结果:

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值