美文网首页
string类的类成员函数

string类的类成员函数

作者: 安然_fc00 | 来源:发表于2017-04-05 20:51 被阅读0次
#include<iostream>
#include<string.h>
class String
{
    public:
        String(const char*str=NULL);
        String(const String&another);
        ~String(); 
        String& operator=(const String &str);
    private:
        char* m_pdata;
};
String::String(const char*str)
{
    if (str==NULL)
    {
        m_pdata=new char[1];
        m_pdata[0]='\0';
    }
    else
    {
        m_pdata=new char[strlen(str)]+1;
        strcpy(m_pdata,str);
    }
}
String::String(const String& another)
{
    m_pdata=new char[strlen(another.m_pdata)+1];
    strcpy(m_pdata,another.m_pdata);
}
String & String::operator=(const String &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;
}
String::~String()
{
    delete[]m_pdata;
}

赋值运算符的实现需要注意以下几点:

  • 连续赋值。把返回值声明为该类型的引用,并在函数结束前返回实例自身的引用*this。
  • 避免无谓消耗。参数类型声明为常量引用,如果传入的不是引用而是实例,那么从形参到实参会调用一次复制构造函数。声明为引用避免这样的无谓消耗,常量保证传入的实例不会被改变。
  • 避免内存泄漏。如果忘记在分配新内存前释放自身已有空间,程序将出现内存泄露。
  • 判断是否是自身。判断传入的实例和自身是否是同一个实例,如果是,那就直接返回该实例,否则在释放实例自身已有空间后就无法再找到需要赋值的内容了。

考虑异常安全的解法:

  • 如果内存不足,导致new char抛出异常,m_pdata将是一个空指针,容易导致程序崩溃,也就是说一旦在赋值运算符函数内部抛出一个异常,String的实例被修改,不再保持有效状态,这就违背了异常安全性原则。
  • 有两种方法:第一种是先用new分配新内容再delete释放已有内容。这样只有new成功后再释放原来的内容,也就是说失败时能保证String的实例不会被修改。更好的方法是先创建一个临时实例,再交换临时实例和原来的实例。
String& String::operator=(const String&str)
{
    if(this!=&str)
    {
        String strTemp(str);
        
        char* pTemp=strTemp.m_pdata;
        strTemp.m_pdata=m_pdata;
        m_pdata=pTemp;
    }
    return *this;
}

该代码中,在String的构造函数里用new分配内存。如果由于内存不足抛出异常,还没有修改原来实例的状态,因此实例的状态还是有效的,保证了异常安全性。

相关文章

网友评论

      本文标题:string类的类成员函数

      本文链接:https://www.haomeiwen.com/subject/bbztattx.html