剑指Offer算法实现之一:赋值运算符函数

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

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

思路:考虑下列问题:
  1. 返回自身的引用
  2. 处理“自我赋值”
  3. 异常安全性
编译环境:ArchLinux+Clang3.3, X86_64
实现一:
    现在临时字符数组上作拷贝,然后与对象的数据成员交换,最后将多余的数组释放。关键代码如下:
CMyString& CMyString::operator=(const CMyString& oth)
{
    if (this == &oth) return *this; // 此句即使略去,自我赋值也不会带来错误,自我复制几率极小,因此不会带来性能问题
    char *tmp = new char[strlen(oth.m_pData)+1]; // 创建临时字符数组
    strcpy(tmp, oth.m_pData);
    swap(m_pData, tmp); // 交换指针,标准库函数
    delete[] tmp; // 释放原对象的数据
    return *this;
}

实现二:
    使用copy-swap技术,解决实现一代码冗余的问题。这样,实现一中临时对象释放问题就可交由CMyString的析构对象负责,并且可充分利用copy构造函数。关键代码如下:
CMyString& CMyString::operator=(const CMyString& oth)
{
    CMyString strTmp{oth}; // copy
    swap(this->m_pData, strTmp.m_pData); // swap(标准库函数)
    return *this;
}

实现三:
   实现二提高了代码复用。也可以使用C++11的move操作符函数和右值引用达到同样的效果。尽管多提供了一个move操作符函数,但对于CMyString这样持有潜在大量动态内存的类来说,不仅可以供编译器优化,而且还可手动调用,这是值得的。
CMyString& CMyString::operator=(CMyString&& oth)
{
    swap(this->m_pData, oth.m_pData); //做了一个swap,this持有的动态内存由oth的析构函数释放
    return *this;
}
CMyString& CMyString::operator=(const CMyString& oth)
{
    CMyString strTmp{oth};
    *this = move(strTmp); // 右值引用语义
    return *this;
}
完整代码:
#include <iostream>
#include <cstring>
using namespace std;

class CMyString{
public:
    CMyString(const char *pData = nullptr);
    CMyString(const CMyString& str);
    CMyString& operator=(const CMyString& oth);
    CMyString& operator=(CMyString&& oth);
    ~CMyString();
    friend ostream& operator<<(ostream& out, CMyString& str);
private:
    char *m_pData;
};
CMyString::CMyString(const char *pData)
{
    if (pData == nullptr){
        m_pData = nullptr;
        return;
    }
    m_pData = new char[strlen(pData)+1];
    strcpy(m_pData, pData);
}
CMyString::CMyString(const CMyString& str)
{
    m_pData = new char[strlen(str.m_pData)+1];
    strcpy(m_pData, str.m_pData);
}
CMyString::~CMyString()
{
    if (m_pData != nullptr) {
        delete[] m_pData;
    }
}
ostream& operator<<(ostream& out, CMyString& str)
{
    return out << str.m_pData;
}
/*
 * 实现一
CMyString& CMyString::operator=(const CMyString& oth)
{
    if (this == &oth) return *this; // 此句即使略去,自我赋值也不会带来问题
    char *tmp = new char[strlen(oth.m_pData)+1];
    strcpy(tmp, oth.m_pData);
    swap(m_pData, tmp);
    delete[] tmp;
    return *this;
}
*/
/* 实现二
CMyString& CMyString::operator=(const CMyString& oth)
{
    CMyString strTmp{oth};
    swap(this->m_pData, strTmp.m_pData);
    return *this;
}
*/
/* 实现三 */
CMyString& CMyString::operator=(CMyString&& oth)
{
    swap(this->m_pData, oth.m_pData);
    return *this;
}
CMyString& CMyString::operator=(const CMyString& oth)
{
    CMyString strTmp{oth};
    *this = move(strTmp);
    return *this;
}

// 测试驱动
int main()
{
    CMyString s{"hello"};
    CMyString t;
    cout << (t = s) << endl;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值