专栏首页C++的沉思C++ string实现
原创

C++ string实现

string经典实现

作为C++从业者,我相信都会被考察过实现简单的string类,包括构造、析构、拷贝构造以及赋值拷贝等,因为这能够很好的考察面试者的C++基本功。借看《剑指offer》的机会将这个问题重新整理一下。具体实现如下:

class string {
public:
    string(const char* cstr = nullptr) 
    {
        if (cstr) {
            m_data = new char[strlen(cstr) + 1];
            strcpy(m_data, cstr);
        } else {
            m_data = new char[1];
            *m_data = '\0';
        }
    }
    string(const string& str) 
    {
        m_data = new char[strlen(str.m_data) + 1];
        strcpy(m_data, str.m_data);
    }
    ~string()
    {
        delete[] m_data;
    }
    string& operator = (const string& rhs) 
    {
        if (this == &rhs)
            return *this;

        delete[] m_data;
        m_data = new char[strlen(rhs.m_data) + 1];
        strcpy(m_data, rhs.m_data);
        return *this;
    }

    friend ostream& operator << (ostream& os, const string& rhs)
    {
        return os << rhs.m_data;
    }
private:
    char* m_data;
};

赋值拷贝

上述代码赋值拷贝将是面试官的考察重点:

  1. 是否将返回值声明为该类型的引用,并且在函数结束前返回实例自身的引用(即*this)。因为只有返回一个引用才可以进行连续赋值。如:str1 = str2 = str3
  2. 是否将传入参数声明为常量引用。如果传入参数不是引用,那么形参到实参会调用一次拷贝构造函数,引用可避免这样无谓消耗,提高代码效率。同时不能改变传入实例的状态,所以要将引用参数加上const关键字。
  3. 是否释放自己的内存。如果忘记在分配新内存之前释放自身已有的空间,程序将出现内存泄漏。
  4. 是否判断传入参数和当前实例(*this)是不是同一个实例。如果是同一个不进行赋值操作,直接返回。如果不实现判断就进行赋值,那么赋值前会释放自身空间,那么传入参数的内存也同时被释放,将再也找不到需要赋值的内容。

考虑异常安全

上面是实现使用于C++初级程序员,但对于C++高级程序员来说还需要考虑异常安全性。前面的实现中,我们在分配内存之前释放了m_data的内存,如果此时内存不足导致new char抛出异常,m_data将是一个空指针,这样非常容易导致程序崩溃。也就是说一旦在赋值运算符函数内部抛出一个异常,string的实例不再保持有效的状态,这就违背了安全性原则。

想要在赋值运算符函数中实现异常安全性,我们有两种方法。一个简单的方法是先用new分配新内容再释放原来空间,另一个更好的方法是先创建一个临时变量,再交换临时变量和原来的实例。代码实现如下:

string& operator = (const string& rhs) 
{
    if (this != &rhs) 
    {
        string tmp(rhs);
        char* p = tmp.m_data;
        tmp.m_data = m_data;
        m_data = p;
    }
    return *this;
}

在上述实现中,先创建一个临时变量tmp,接着将tmp.m_data和自身的m_data交换,由于tmp是一个局部变量,出了作用域就会调用析构函数将内存释放掉。如果临时变量调用构造函数时,由于内存不足抛出bad_alloc等异常,我们还没有修改原来实例的状态,因此实例是有效的,这保证了异常安全性。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 从位图原理到布隆过滤器的实现

    假设一个int占4个字节(32位),40个亿个整数就是160亿个字节,大概相当于16GB,假设一台计算机只有2GB内存,则16GB一次加载不完,需要分8次加载,...

    evenleo
  • 归并快排算法比较及求第K大元素

    核心思想:将数组从中间分成前后两部分,然后对前后两部分分别进行排序,再将排序好的两个部分有序合并在一起,这样整个数组有序。全文图示来源于王争的《数据结构和算法之...

    evenleo
  • C++多线程如何获取真正安全的单例

    如果你认为有两种可能,1、2和3、4的话,那说明你是按典型的程序员思维看问题的--没有像编译器和处理器一样处理问题。事实上, 1、4也是一种可能的结果。有两个基...

    evenleo
  • R分类算法-神经网络算法

    神经网络(Artifical Neural Network) 神经网络(人工神经网络),是一种模仿生物网络(动物的中枢神经系统,特别是大脑)的结构和功能的数学模...

    Erin
  • [半zz]迅雷笔试题

    用户1130771
  • 讲讲切比雪夫定理

    前面讲了大数定理,讲了中心极限定理,有读者留言让讲讲切比雪夫定理,安排。这一篇就来讲讲切比雪夫定理。

    张俊红
  • 从0到1掌握R语言网络爬虫

    引言 网上的数据和信息无穷无尽,如今人人都用百度谷歌来作为获取知识,了解新鲜事物的首要信息源。所有的这些网上的信息都是直接可得的,而为了满足日益增长的数据需求,...

    小莹莹
  • 【学习】笨办法学R编程(三)

    看到各位对“笨办法系列”的东西还比较感兴趣,我也很乐意继续写下去。今天的示例将会用到数据框(data.frame)这种数据类型,并学习如何组合计算...

    小莹莹
  • pandas的一些小知识

    生信编程日常
  • WordPress发布/更新文章、提交/审核评论自动清理VeryCloud缓存

    上一篇文章分享了WordPress 发布文章评论自动刷新腾讯云 CDN 的教程,而博客现在还用到了 VeryCloud 的 CDN,正好有朋友在文章后面留言说 ...

    张戈

扫码关注云+社区

领取腾讯云代金券