剑指offer1:赋值运算符函数

#include<iostream>
using namespace std;
class CMyString{
public:
    CMyString(char* pData=NULL)
    {
        m_pData=pData;
    }
    CMyString(const CMyString& str)
    {
        m_pData=str.m_pData;
    }
    CMyString& operator = (const CMyString& str);
    int display()
    {
        int address=reinterpret_cast<int>(m_pData);//具体可以参考上一篇文章中,关于c++中强制类型转换
        return address;
    }
    ~CMyString()
    {
    }
private:
    char* m_pData;

};
CMyString& CMyString::operator=(const CMyString& str)
{
    if(this!=&str)
    {
        CMyString tmpString(str);//先利用拷贝构造函数构造传入参数的副本

        char* pTemp=tmpString.m_pData;//交换副本和当前对象的m_pData
        tmpString.m_pData=m_pData;
        m_pData=pTemp;
    }//当跳出if语句块后,tmpString会自动调用析构函数进行内存的释放,也就释放了当前对象所指向的内存空间
    return *this;
}
int main()
{
    char* c=new char('a');
    CMyString s1(c);
    cout<<"s1:"<<s1.display()<<endl;
    CMyString s2(s1);
    cout<<"s2:"<<s2.display()<<endl;
    CMyString s3=s2;
    cout<<"s3:"<<s3.display()<<endl;

    return 0;
}

运行结果:
这里写图片描述
可以发现三个类对象实例的地址都是相同,也就是说没有重新开辟新内存,都是将指针指向同一个内存地址,完成赋值操作。一方面避免重新开辟内存时出现内存分配失败,一方面也提高的赋值效率,仅仅是指针的指向而已。

#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
class CMyString{
public:
    CMyString(char* pData=NULL)
    {
        m_pData=pData;
    }
    CMyString(const CMyString& str)
    {
        m_pData=new char[strlen(str.m_pData)+1];
        strcpy(m_pData,str.m_pData);
    }
    CMyString& operator = (const CMyString& str);
    int display()
    {
        int address=reinterpret_cast<int>(m_pData);
        return address;
    }
    ~CMyString()
    {
    }
private:
    char* m_pData;

};
CMyString& CMyString::operator=(const CMyString& str)
{
    if(this==&str)
        return *this;
    delete[] m_pData;
    m_pData=NULL;
    m_pData=new char[strlen(str.m_pData)+1];
    strcpy(m_pData,str.m_pData);
    return *this;
}
int main()
{
    char* c=new char('a');
    CMyString s1(c);
    cout<<"s1:"<<s1.display()<<endl;
    CMyString s2(s1);
    cout<<"s2:"<<s2.display()<<endl;
    CMyString s3=s2;
    cout<<"s3:"<<s3.display()<<endl;

    return 0;
}

运行结果:
这里写图片描述
可见三个对象实例中的m_pData的地址是不相同的,但是这里同样存在一个问题,就是new char语句很有可能出现分配内存失败的情况,所以此时将导致程序崩溃。这是一种深拷贝的问题。

几点注意:

  1. 返回类型需要声明为该类的引用,所以返回的是*this.因为我们知道在一个类中,this是指向当前对象的指针,那么指针中的类容*this自然就是当前对象的地址,即该类型的引用。之所以要这样声明,是为了可以连续赋值操作;
  2. 函数参数需要声明为常量引用。分两部讲,引用的目的是因为,如果声明为类的实例,那么从形参到实参就存在一次拷贝,会调用类的拷贝构造函数,这样非常的消耗资源,声明引用就不存在这个问题;常量是因为,我们是赋值操作,当然不希望修改实参的内容;
  3. 是否释放实例自身已有的内存,如果忘记,则会出现内存泄露的情况。(在计算机科学中,内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。)
  4. 是否判断当前传入的参数和实例自身是不是同一对象,如果是同一个则不进行赋值操作,直接返回,否则两者是同一对象的情况下依然进行赋值操作,那么首先我们就会释放实例自身已有的内存,那么这样传入的参数的内存同时也被释放了,也就造成这段内容永远的消失了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值