String类赋值运算符函数

原创 2016年06月01日 22:22:54

题目:如下类型CMyString的声明,请为该类添加赋值运算符函数

class CMyString
{
public:
    CMyString(char* pdata = NULL);
    CMyString(const CMyString& str);
    //赋值函数
    CMyString& operator=(const CMyString& str); 

    ~CMyString(); 

private:
    char* m_data;
};

面试官考察的点:
1、 是否把返回值的类型声明为该类型的引用,并在函数返回前,返回自身的引用(*this)。只有返回一个引用,才可以允许连续赋值。如果函数的返回值为void,则像str1=str2=str3这样的连续赋值将不会被通过
2、 是否把传入的参数类型声明为常引用。如果传入的参数不是引用而是实=实例的话,那么从形参到实参要进行一次拷贝构造函数的调用,把参数声明为引用,可以避免无谓的消耗,提高效率。同时,在赋值的时候,不应该改变传入参数的状态,所以,应该声明为常引用,加上const关键字
3、 是否释放自身的空间,否则程序将出现内存泄漏
4、 避免自赋值。判断传入的参数是否和当前的实例*this是一个实例,如果是同一个实例,则不进行赋值操作,直接返回。如果事先不进行判断,在释放自身实例的内存的时候就会出现问题,一旦释放了自身的内存,传入的参数的内存也同时释放了,因此再也找不到需要赋值的内容了

//初级程序员解法:

CMyString& CMyString::operator=(const CMyString& str)
{
    //防止自赋值
    if (&str == this)
        return *this;
    //释放自身空间
    delete[] m_data;
    m_data = NULL; 
    //分配空间,赋值
    m_data = new char[strlen(str.m_data)+1]; 
    strcpy(m_data, str.m_data); 

    //返回自身引用
    return *this; 
}

//考虑异常安全的解法,高级程序员必备
在前面的函数中,我们在分配内存之前先delete释放了自身的内存。但是如果此时内存不足,分配内存的时候抛出异常,那么m_data将是一个空指针,很容易导致程序崩溃,违背了异常安全原则
要想在赋值函数中实现异常安全性。有两种方法:1、一个简单的方法是先用new分配新内容,再delete释放已有的内容,这样在分配成功之后再释放原来的内容,也就是当分配失败时可以保证CMyString的实例不会被修改。2、还有一个更好的方法就是创建一个临时对象,再交换临时对象和原来对象

CMyString& CMyString::operator=(const CMyString& str)
{
    if (&str != this)
    {
        //先通过拷贝构造函数创建一个临时对象 
        CMyString strtmp(str);
        //交换临时对象和自身的m_data
        char* pTmp = m_data;
        m_data = strtmp.m_data;
        strtmp.m_data = pTmp; 

    }
    return *this;
}

这个函数中,先创建一个临时对象,然后交换临时对象和实例自身的m_data,由于临时对象是一个局部对象,出了if语句就会自动调用临时对象的析构函数,就会把临时对象所指的那块内存释放掉。
在这个新的代码中,我们在CMyString的构造函数里用new分配内存,如果内存不足抛出异常,这时,我们还没有修改原来实例的状态。就保证了异常安全性

版权声明:本文为博主原创文章,未经博主允许不得转载。

C++ 类赋值运算符函数

声明类型CMyString,为该类型添加赋值运算符 Class CMyString { Public:     CMyString(char* pData=NULL);     CMyStr...
  • CodeAsWind
  • CodeAsWind
  • 2014年07月17日 12:19
  • 1296

剑指offer面试题(一):赋值运算符函数

对于定义一个赋值运算符函数时,需要注意一下几点: (1)函数的返回类型必须是一个引用,因为只有返回引用,才可以连续赋值 (2)传入的参数声明为常量引用,可以提高代码效率,同时赋值运算函数内不会改变...
  • kerry0071
  • kerry0071
  • 2014年09月15日 11:41
  • 3248

剑指offer——面试题1:赋值运算符函数

题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数。 class CMyString { public: CMyString(char* pData = NULL); CMyStr...
  • sinat_20265495
  • sinat_20265495
  • 2016年06月10日 16:04
  • 350

重载赋值运算符

  重载赋值运算符赋值运算符可能是最容易令人迷惑的一个,所以,重载它必须十分的小心。1. 值运算符仅能重载为成员函数。C++不允许赋值运算符被重载为全局形式,这是因为如果可以写出全局形式的赋值运算符函...
  • wptad
  • wptad
  • 2007年07月22日 21:33
  • 10038

【C++】赋值运算符函数

将已有的对象拷贝给另一个对象时,会用到赋值运算符函数, 尤其是当对象的内存分配在堆上时 函数原型: ClassName & operator = (const ClassName &obj) ...
  • michellechouu
  • michellechouu
  • 2015年08月05日 16:27
  • 3146

C++9.3.8 赋值与swap

简介 与赋值相关的操作符都作用于整个容器 ===============================================================================...
  • hlsdbd1990
  • hlsdbd1990
  • 2015年06月08日 09:16
  • 619

C++类的赋值运算符“=”重载,以及深拷贝和浅拷贝

C++类的赋值运算符“=”重载,以及深拷贝和浅拷贝 在面向对象程序设计中,对象间的相互拷贝和赋值是经常进行的操作。 如果对象在申明的同时马上进行初始化操作,则称之为拷贝运算。例如: class1 A(...
  • liubing8609
  • liubing8609
  • 2014年11月23日 14:51
  • 2786

C++之重写String类

C++之重写String类        有时候听完课程,不一定就能够领悟,所以还是要多加练习,今天在听了老师讲的C++关于类的构造函数,默认构造函数,类的拷贝函数(浅拷贝/深拷贝),类的析构函数,...
  • wxm349810930
  • wxm349810930
  • 2016年09月16日 08:25
  • 1141

剑指offer 面试题1:赋值运算符函数

题目描述: 如下为类型CMyString的声明,请为该类型添加赋值运算符函数。 题目分析: 定义一个赋值运算符函数,应注意以下几点: 1)返回值的类型应为该实力自身的引用(即*this)。返回引用,才...
  • Mary19920410
  • Mary19920410
  • 2017年08月18日 14:55
  • 130

剑指offer - 赋值运算符函数

如下为类型CMyString的声明,为该类型添加赋值运算符函数: class CMyString{ public : CMyString(char* pData = NUL...
  • zkp0601
  • zkp0601
  • 2015年09月19日 12:16
  • 432
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:String类赋值运算符函数
举报原因:
原因补充:

(最多只允许输入30个字)