c++ 赋值运算符函数

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

class CMyString{
 public:
    CMyString(char* pData = nullptr);
    CMyString(const CMyString& str);
    ~CMyString(void);
private:
    char* m_pData;
};

普通写法:

CMyString &CMyString::operator=(const CMyString &str) // 如果传入的参数不是引用而是实例,那么从形参到实参会调用一次复制构造函数,造成浪费,在赋值运算函数内不会改变传入的实例的状态,所以用const 关键字
{
     if (this == &str) {
         return *this; //如果不判断会导致严重内存泄漏的问题,自身实例也会被析构
     }
    delete[] m_pData;
     m_pData = nullptr;

     m_pData = new char[strlen(str.m_pData) + 1];
     strcpy(m_pData, str.m_pData);
  
    return *this; //只有返回一个引用,才会允许连续赋值
}

 可能存在的问题,如果在 new char 抛出异常,m_pData 将是一个空指针,这样非常容易导致程序崩溃,违背 异常安全性原则

安全写法:

CMyString &CMyString::operator=(const CMyString &str)
{
    /*
     if (this == &str) {
         return *this;
     }
    delete[] m_pData;
     m_pData = nullptr;

     m_pData = new char[strlen(str.m_pData) + 1];
     strcpy(m_pData, str.m_pData);
  */
    if (this != &str) {
        CMyString strTemp(str);

        char *pTemp = strTemp.m_pData;
        strTemp.m_pData = m_pData;
        m_pData = pTemp;
    }
    return *this;
}

在这个函数中,我们先创建一个临时实例 str Temp,接着把 strTemp.m_pData 和实例自身的 mpData 进行交换。由于strTemp 是一个局部变量,但程序运行到 记 的外面时也就出了该变量的作用域,就会自动调用 strTemp的析构函数,把strTemp.m pData所指向的内存释放掉。由于
str Temp.m pData 指向的内存就是实例之前 m pData 的内存,这就相当于自动调用析构函数释放实例的内存。

完整代码:

#include <QCoreApplication>
#include <cstring>
#include <iostream>
#include <ostream>

class CMyString
{
public:
    CMyString(char *pData = nullptr);
    CMyString(const CMyString &str);
    ~CMyString(void);
    CMyString &operator=(const CMyString &str);
    friend std::ostream &operator<<(std::ostream &os, const CMyString &str);

private:
    char *m_pData;
};

CMyString &CMyString::operator=(const CMyString &str)
{
    /*
     if (this == &str) {
         return *this;
     }
    delete[] m_pData;
     m_pData = nullptr;

     m_pData = new char[strlen(str.m_pData) + 1];
     strcpy(m_pData, str.m_pData);
  */
    if (this != &str) {
        CMyString strTemp(str);

        char *pTemp = strTemp.m_pData;
        strTemp.m_pData = m_pData;
        m_pData = pTemp;
    }
    return *this;
}

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

CMyString::~CMyString(void)
{
    delete m_pData;
    m_pData = nullptr;
}

CMyString::CMyString(const CMyString &str)
{
    int len = strlen(str.m_pData) + 1;
    m_pData = new char(len);
    m_pData = str.m_pData;
}

std::ostream &operator<<(std::ostream &os, const CMyString &str)
{
    os << str.m_pData;
    return os;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    char *c = "string";
    CMyString b(c);
    CMyString d = b;

    std::cout << "b = " << b << "     "
              << "d =" << d << std::endl;
    return a.exec();
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值