云计算百科
云计算领域专业知识百科平台

《STL string 底层复刻:动态数组、拷贝控制与性能优化》

提起 C++ 中的 string,想必不少人都有过这样的感触:初学时惊叹于它功能的丰富与便捷,总忍不住感慨这份 “开箱即用” 的神奇;深入学习后才发现,这份看似简单的 “神奇” 背后,藏着动态内存管理、拷贝控制、运算符重载等层层精巧的底层设计

std::string的使用  点击可以看到标准库中string的主要功能。

目录

第一步:开一个string.h的头文件

1. 代码结构分析

1.构造函数:

        浅拷贝:

        深拷贝:

核心思路:

优势:

延伸:拷贝赋值运算符也可以用这个写法

2.析构函数:

3.常用成员函数:

        1.iterator(迭代器)

        2.常调用的函数或简单的函数

补充:

4.较复杂的成员函数   string.cpp

1.实现,无注释版:

2.代码注释版

5.运算符重载实现字符串比较和输入输出功能

1.比较运算符重载

2.流运算符重载

关键实现细节说明

6.完整代码

string.h

string.cpp


接下来,我们来讲怎么实现string

第一步:开一个string.h的头文件

1. 代码结构分析

#pragma once
#include <iostream>
#include <assert.h>
using namespace std;

namespace bit
{
class string
{
private:
char* _str = nullptr; // 指向堆上的字符数组
size_t _size = 0; // 当前有效字符个数(不含'\\0')
size_t _capacity = 0; // 当前可存储的最大字符数(不含'\\0')
};
}

  • _str:指向动态分配的字符数组,是字符串的实际存储位置。
  • _size:记录当前字符串的有效长度,避免每次都调用 strlen 计算。
  • _capacity:记录当前分配的内存容量,用于实现动态扩容,避免频繁分配内存。
  • 使用 namespace bit ,可以避免与标准库 std::string 冲突。

基于这个框架,可以逐步实现以下核心功能:

  • 构造函数:

    • 默认构造:string()
    • 从 C 字符串构造:string(const char* s)
    • 拷贝构造:string(const string& s)
    • 移动构造:string(string&& s)
  • 析构函数:

    • 释放 _str 指向的堆内存,避免内存泄漏。
  • 运算符重载:

    • 拷贝赋值:string& operator=(const string& s)
    • 移动赋值:string& operator=(string&& s)
    • 下标访问:char& operator[](size_t pos)
    • 流输出:friend ostream& operator<<(ostream& os, const string& s)
  • 常用成员函数:

    • size() / length():返回 _size
    • c_str():返回 _str
    • push_back(char ch):在末尾添加字符
    • append(const string& s):追加字符串
    • resize(size_t n) / reserve(size_t n):调整大小和容量

  • 1.构造函数:

            浅拷贝:

    /*string()
    :_str(new char[1]{'\\0'})
    ,_size(0)
    ,_capacity(0)
    {}*/

    // 短小频繁调用的函数,可以直接定义到类里面,默认是inline
    // 代替string().优化写法
    string(const char* str = "") // " "中间默认是\\0
    {
    _size = strlen(str);
    // _capacity不包含\\0
    _capacity = _size;
    _str = new char[_capacity + 1]; // 需要额外开一个空间存放"\\0"
    strcpy(_str, str);
    }

            深拷贝:

    // 深拷贝问题
    // s2(s1)
    /*string(const string& s)
    {
    _str = new char[s._capacity + 1];
    strcpy(_str, s._str);
    _size = s._size;
    _capacity = s._capacity;
    }*/

    //优化写法
    // 辅助函数:交换两个对象的所有资源
    void swap(string& s)
    {
    std::swap(_str, s._str);
    std::swap(_size, s._size);
    std::swap(_capacity, s._capacity);
    }

    // 拷贝构造函数(现代写法)
    string(const string& s)
    {
    string tmp(s._str); // 1. 先构造一个临时对象tmp,它是s的副本
    swap(tmp); // 2. 把当前对象(this)和tmp交换
    }

    核心思路:
  • 复用已有构造函数:先利用已有的 string(const char*) 构造函数,创建一个临时对象 tmp,它已经是 s 的完整副本(包含正确的内存、大小和容量)。
  • 交换资源:通过 swap 函数,把当前对象(this)的空资源(默认初始化的 _str = nullptr、_size = 0、_capacity = 0)和 tmp 的有效资源交换。
  • 自动清理:当 tmp 离开作用域时,它的析构函数会自动释放掉原来 this 所持有的空资源,整个过程安全且自动。
  • 优势:
    • 代码极简:复用了已有构造函数,避免了重复的内存分配和拷贝逻辑。
    • 异常安全:如果构造 tmp 时抛出异常(如内存不足),当前对象 this 保持初始的空状态,不会处于半构造的无效状态。

    延伸:拷贝赋值运算符也可以用这个写法

    // s1 = s3;
    //string& operator=(const string& s)
    //{
    //if (this != &s)
    //{
    ////string tmp(s._str);
    //string tmp(s);
    //swap(tmp);
    //}
    //return *this;
    //}

    // s1 = s3;
    string& operator=(string tmp)// 注意:参数是值传递,会自动调用拷贝构造
    {
    swap(tmp);// 直接和临时对象交换
    return *this;
    }

    • 参数 s 是一个值传递的副本,函数结束后会自动析构,释放掉 this 原来的旧资源。
    • 这是 C++ 中实现强异常安全拷贝赋值的经典方案。

    2.析构函数:

    ~string()
    {
    if (_str)
    {
    delete[] _str;
    _str = nullptr;
    _size = _capacity = 0;
    }
    }

    释放 _str 指向的堆内存,避免内存泄漏。


    3.常用成员函数:

            1.iterator(迭代器)

    public:
    typedef char* iterator;
    typedef const char* const_iterator;

    iterator begin()
    {
    return _str;
    }

    iterator end()
    {
    return _str + _size;
    }

    const_iterator begin() const
    {
    return _str;
    }

    const_iterator end() const
    {
    return _str + _size;
    }

            2.常调用的函数或简单的函数

    //注意:以下都是成员函数,在class string {} 内部
    //若string s1,以下是用法 s1.成员函数();

    //s1.c_str;

    const char* c_str() const
    {
    return _str;
    }

    //s1.clear();
    void clear()
    {
    _str[0] = '\\0';
    _size = 0;
    }

    //s1.size();
    size_t size() const
    {
    return _size;
    }

    size_t capacity() const
    {
    return _capacity;
    }

    char& operator[](size_t pos)
    {
    assert(pos < _size);

    return _str[pos];
    }

    const char& operator[](size_t pos) const
    {
    assert(pos < _size);

    return _str[pos];
    }

    对于常调用的函数或简单的函数,可以直接在头文件中定义

    短小频繁调用的函数,可以直接定义到类里面,默认是inline

    补充:

    内联函数与头文件定义

    在头文件中直接定义简单函数时,通常会使用inline关键字来避免多重定义错误。内联函数建议满足以下条件:

    • 函数体简短(通常不超过10行)
    • 调用频率高
    • 不含递归或复杂控制流

    4.较复杂的成员函数   string.cpp

    只声明不实现:复杂函数的实现全部放在 .cpp 文件中,头文件只保留声明,减少编译依赖;

    //string.h

    void reserve(size_t n);
    void push_back(char ch);
    void append(const char* str);
    string& operator+=(char ch);
    string& operator+=(const char* str);

    void insert(size_t pos, char ch);
    void insert(size_t pos, const char* str);
    void erase(size_t pos, size_t len = npos);

    size_t find(char ch, size_t pos = 0);
    size_t find(const char* str, size_t pos = 0);
    string substr(size_t pos = 0, size_t len = npos);

    1.实现,无注释版:

    这里要注意:在string.h中有默认参数,在string.cpp中不要再写。如下文的 find.

    #include"string.h"

    namespace bit
    {
    const size_t string::npos = -1;

    void string::reserve(size_t n)
    {
    if (n > _capacity)
    {
    //cout << "reserve:" << n << endl;

    char* tmp = new char[n + 1];
    strcpy(tmp, _str);
    delete[] _str;
    _str = tmp;
    _capacity = n;
    }
    }

    void string::push_back(char ch)
    {
    if (_size == _capacity)
    {
    reserve(_capacity == 0 ? 4 : _capacity * 2);
    }

    _str[_size] = ch;
    ++_size;
    _str[_size] = '\\0';
    }

    string& string::operator+=(char ch)
    {
    push_back(ch);
    return *this;
    }

    void string::append(const char* str)
    {
    size_t len = strlen(str);
    if (_size + len > _capacity)
    {
    // 大于2倍,需要多少开多少,小于2倍按2倍扩
    reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
    }

    strcpy(_str + _size, str);
    _size += len;
    }

    string& string::operator+=(const char* str)
    {
    append(str);
    return *this;
    }

    void string::insert(size_t pos, char ch)
    {
    assert(pos <= _size);

    if (_size == _capacity)
    {
    reserve(_capacity == 0 ? 4 : _capacity * 2);
    }

    // 挪动数据
    size_t end = _size + 1;
    while (end > pos)
    {
    _str[end] = _str[end – 1];
    –end;
    }

    _str[pos] = ch;
    ++_size;
    }

    void string::insert(size_t pos, const char* s)
    {
    assert(pos <= _size);

    size_t len = strlen(s);
    if (_size + len > _capacity)
    {
    // 大于2倍,需要多少开多少,小于2倍按2倍扩
    reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
    }

    size_t end = _size + len;
    while (end > pos + len – 1)
    {
    _str[end] = _str[end – len];
    –end;
    }

    for (size_t i = 0; i < len; i++)
    {
    _str[pos + i] = s[i];
    }

    _size += len;
    }

    void string::erase(size_t pos, size_t len)
    {
    assert(pos < _size);

    if (len >= _size – pos)
    {
    _str[pos] = '\\0';
    _size = pos;
    }
    else
    {
    for (size_t i = pos + len; i <= _size; i++)
    {
    _str[i – len] = _str[i];
    }

    _size -= len;
    }
    }

    size_t string::find(char ch, size_t pos)
    {
    assert(pos < _size);

    for (size_t i = pos; i < _size; i++)
    {
    if (_str[i] == ch)
    {
    return i;
    }
    }

    return npos;
    }

    size_t string::find(const char* str, size_t pos)
    {
    assert(pos < _size);

    const char* ptr = strstr(_str + pos, str);
    if (ptr == nullptr)
    {
    return npos;
    }
    else
    {
    return ptr – _str;
    }
    }

    string string::substr(size_t pos, size_t len)
    {
    assert(pos < _size);

    // len大于剩余字符长度,更新一下len
    if (len > _size – pos)
    {
    len = _size – pos;
    }

    string sub;
    sub.reserve(len);
    for (size_t i = 0; i < len; i++)
    {
    sub += _str[pos + i];
    }

    return sub;
    }

    2.代码注释版

    #include"string.h"

    namespace bit
    {
    // 定义静态成员npos,表示无效位置或未找到
    const size_t string::npos = -1;

    // 调整字符串容量至至少n个字符(不包括结尾的'\\0')
    void string::reserve(size_t n)
    {
    if (n > _capacity)
    {
    // 分配新内存(多1字节用于存储'\\0')
    char* tmp = new char[n + 1];
    // 复制原内容到新内存
    strcpy(tmp, _str);
    // 释放旧内存
    delete[] _str;
    _str = tmp;
    _capacity = n;
    }
    }

    // 在字符串末尾追加字符
    void string::push_back(char ch)
    {
    // 容量不足时扩容(初始为0则扩容至4)
    if (_size == _capacity)
    {
    reserve(_capacity == 0 ? 4 : _capacity * 2);
    }

    // 写入字符并更新大小和结尾'\\0'
    _str[_size] = ch;
    ++_size;
    _str[_size] = '\\0';
    }

    // 重载+=运算符(字符版本)
    string& string::operator+=(char ch)
    {
    push_back(ch);
    return *this;
    }

    // 追加C风格字符串
    void string::append(const char* str)
    {
    size_t len = strlen(str);
    // 容量不足时扩容(按需或2倍扩容策略)
    if (_size + len > _capacity)
    {
    reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
    }

    // 追加内容并更新大小
    strcpy(_str + _size, str);
    _size += len;
    }

    // 重载+=运算符(字符串版本)
    string& string::operator+=(const char* str)
    {
    append(str);
    return *this;
    }

    // 在指定位置插入字符
    void string::insert(size_t pos, char ch)
    {
    assert(pos <= _size);

    // 容量不足时扩容
    if (_size == _capacity)
    {
    reserve(_capacity == 0 ? 4 : _capacity * 2);
    }

    // 向后移动数据腾出位置
    size_t end = _size + 1;
    while (end > pos)
    {
    _str[end] = _str[end – 1];
    –end;
    }

    // 插入字符并更新大小
    _str[pos] = ch;
    ++_size;
    }

    // 在指定位置插入C风格字符串
    void string::insert(size_t pos, const char* s)
    {
    assert(pos <= _size);

    size_t len = strlen(s);
    // 容量不足时扩容
    if (_size + len > _capacity)
    {
    reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
    }

    // 移动原有数据
    size_t end = _size + len;
    while (end > pos + len – 1)
    {
    _str[end] = _str[end – len];
    –end;
    }

    // 插入新字符串内容
    for (size_t i = 0; i < len; i++)
    {
    _str[pos + i] = s[i];
    }

    _size += len;
    }

    // 删除从pos开始的len个字符
    void string::erase(size_t pos, size_t len)
    {
    assert(pos < _size);

    // 若删除范围超过字符串尾部,则截断到pos位置
    if (len >= _size – pos)
    {
    _str[pos] = '\\0';
    _size = pos;
    }
    else
    {
    // 向前移动剩余字符覆盖被删除部分
    for (size_t i = pos + len; i <= _size; i++)
    {
    _str[i – len] = _str[i];
    }
    _size -= len;
    }
    }

    // 从pos位置开始查找字符ch
    size_t string::find(char ch, size_t pos)
    {
    assert(pos < _size);

    // 线性搜索匹配字符
    for (size_t i = pos; i < _size; i++)
    {
    if (_str[i] == ch)
    {
    return i;
    }
    }

    return npos;
    }

    // 从pos位置开始查找子串str
    size_t string::find(const char* str, size_t pos)
    {
    assert(pos < _size);

    // 使用strstr函数查找子串
    const char* ptr = strstr(_str + pos, str);
    if (ptr == nullptr)
    {
    return npos;
    }
    else
    {
    return ptr – _str;
    }
    }

    // 提取从pos开始长度为len的子串
    string string::substr(size_t pos, size_t len)
    {
    assert(pos < _size);

    // 调整len不超过剩余字符数
    if (len > _size – pos)
    {
    len = _size – pos;
    }

    // 创建子串对象并预分配空间
    string sub;
    sub.reserve(len);
    // 逐个字符复制
    for (size_t i = 0; i < len; i++)
    {
    sub += _str[pos + i];
    }

    return sub;
    }
    }


    5.运算符重载实现字符串比较和输入输出功能

    #pragma once
    #include<iostream>
    #include<assert.h>
    using namespace std;

    namespace bit
    {
    class string
    {
    //……

    };

    bool operator<(const string& s1, const string& s2);
    bool operator<=(const string& s1, const string& s2);
    bool operator>(const string& s1, const string& s2);
    bool operator>=(const string& s1, const string& s2);
    bool operator==(const string& s1, const string& s2);
    bool operator!=(const string& s1, const string& s2);

    ostream& operator<<(ostream& out, const string& s);
    istream& operator>>(istream& in, string& s);
    }

    1.比较运算符重载

    bool operator<(const string& s1, const string& s2)
    {
    // 使用strcmp比较两个字符串的C风格字符串形式
    // 返回s1是否按字典序小于s2
    return strcmp(s1.c_str(), s2.c_str()) < 0;
    }

    bool operator<=(const string& s1, const string& s2)
    {
    // 小于或等于运算通过组合<和==运算符实现
    return s1 < s2 || s1 == s2;
    }

    bool operator>(const string& s1, const string& s2)
    {
    // 大于运算通过否定<=运算实现
    return !(s1 <= s2);
    }

    bool operator>=(const string& s1, const string& s2)
    {
    // 大于等于运算通过否定<运算实现
    return !(s1 < s2);
    }

    bool operator==(const string& s1, const string& s2)
    {
    // 相等运算使用strcmp比较C风格字符串
    return strcmp(s1.c_str(), s2.c_str()) == 0;
    }

    bool operator!=(const string& s1, const string& s2)
    {
    // 不等运算通过否定==运算实现
    return !(s1 == s2);
    }

    2.流运算符重载

    ostream& operator<<(ostream& out, const string& s)
    {
    // 遍历字符串的每个字符并输出到输出流
    for (auto ch : s)
    {
    out << ch;
    }
    return out; // 返回输出流以支持链式调用
    }

    istream& operator>>(istream& in, string& s)
    {
    s.clear(); // 清空目标字符串

    const int N = 256; // 缓冲区大小
    char buff[N]; // 字符缓冲区
    int i = 0; // 缓冲区索引

    char ch;
    ch = in.get(); // 使用get()读取单个字符(包括空格)

    // 读取直到遇到空格或换行符
    while (ch != ' ' && ch != '\\n')
    {
    buff[i++] = ch;

    // 缓冲区满时处理
    if (i == N – 1)
    {
    buff[i] = '\\0'; // 添加字符串结束符
    s += buff; // 将缓冲区内容追加到字符串

    i = 0; // 重置缓冲区索引
    }

    ch = in.get(); // 读取下一个字符
    }

    // 处理缓冲区剩余内容
    if (i > 0)
    {
    buff[i] = '\\0';
    s += buff;
    }

    return in; // 返回输入流以支持链式调用
    }

    关键实现细节说明

    比较运算符实现特点 所有比较运算符都基于strcmp函数实现,确保与C风格字符串比较行为一致。通过运算符间的逻辑组合减少重复代码,如>和>=分别通过否定<=和<实现。

    流运算符实现特点 输出运算符直接遍历字符串字符,简单高效。输入运算符采用缓冲技术处理长字符串,避免频繁内存分配。使用get()而非>>读取字符,确保能捕获空格字符作为输入终止符。

    缓冲区管理 输入运算符使用固定大小缓冲区(256字节)分批处理输入,平衡内存使用和性能。当缓冲区接近满时及时清空,防止溢出同时减少字符串拼接操作。


    6.完整代码

    string.h

    #pragma once
    #include<iostream>
    #include<assert.h>
    using namespace std;

    namespace bit
    {
    class string
    {
    public:
    typedef char* iterator;
    typedef const char* const_iterator;

    iterator begin()
    {
    return _str;
    }

    iterator end()
    {
    return _str + _size;
    }

    const_iterator begin() const
    {
    return _str;
    }

    const_iterator end() const
    {
    return _str + _size;
    }

    /*string()
    :_str(new char[1]{'\\0'})
    ,_size(0)
    ,_capacity(0)
    {}*/

    // 短小频繁调用的函数,可以直接定义到类里面,默认是inline
    //代替string()
    string(const char* str = "")
    {
    _size = strlen(str);
    // _capacity不包含\\0
    _capacity = _size;
    _str = new char[_capacity + 1];
    strcpy(_str, str);
    }

    // 深拷贝问题
    // s2(s1)
    /*string(const string& s)
    {
    _str = new char[s._capacity + 1];
    strcpy(_str, s._str);
    _size = s._size;
    _capacity = s._capacity;
    }*/

    void swap(string& s)
    {
    std::swap(_str, s._str);
    std::swap(_size, s._size);
    std::swap(_capacity, s._capacity);
    }

    // s2(s1)
    // 现代写法
    string(const string& s)
    {
    string tmp(s._str);
    swap(tmp);
    }

    // s2 = s1
    // s1 = s1
    /*string& operator=(const string& s)
    {
    if (this != &s)
    {
    delete[] _str;

    _str = new char[s._capacity + 1];
    strcpy(_str, s._str);
    _size = s._size;
    _capacity = s._capacity;
    }

    return *this;
    }*/

    // s1 = s3;
    //string& operator=(const string& s)
    //{
    //if (this != &s)
    //{
    ////string tmp(s._str);
    //string tmp(s);

    //swap(tmp);
    //}

    //return *this;
    //}

    // s1 = s3;
    string& operator=(string tmp)
    {
    swap(tmp);

    return *this;
    }

    ~string()
    {
    if (_str)
    {
    delete[] _str;
    _str = nullptr;
    _size = _capacity = 0;
    }
    }

    const char* c_str() const
    {
    return _str;
    }

    void clear()
    {
    _str[0] = '\\0';
    _size = 0;
    }

    size_t size() const
    {
    return _size;
    }

    size_t capacity() const
    {
    return _capacity;
    }

    char& operator[](size_t pos)
    {
    assert(pos < _size);

    return _str[pos];
    }

    const char& operator[](size_t pos) const
    {
    assert(pos < _size);

    return _str[pos];
    }

    /*void copy_on_write()
    {
    if (count > 1)
    {
    深拷贝
    }
    }*/

    void reserve(size_t n);
    void push_back(char ch);
    void append(const char* str);
    string& operator+=(char ch);
    string& operator+=(const char* str);

    void insert(size_t pos, char ch);
    void insert(size_t pos, const char* str);
    void erase(size_t pos, size_t len = npos);

    size_t find(char ch, size_t pos = 0);
    size_t find(const char* str, size_t pos = 0);
    string substr(size_t pos = 0, size_t len = npos);
    private:
    //char _buff[16];
    char* _str = nullptr;
    size_t _size = 0;
    size_t _capacity = 0;

    //static const size_t npos = -1;
    static const size_t npos;

    /*static const int N = 10;
    int buff[N];*/
    };

    bool operator<(const string& s1, const string& s2);
    bool operator<=(const string& s1, const string& s2);
    bool operator>(const string& s1, const string& s2);
    bool operator>=(const string& s1, const string& s2);
    bool operator==(const string& s1, const string& s2);
    bool operator!=(const string& s1, const string& s2);

    ostream& operator<<(ostream& out, const string& s);
    istream& operator>>(istream& in, string& s);
    }

    string.cpp

    #include"string.h"

    namespace bit
    {
    const size_t string::npos = -1;

    void string::reserve(size_t n)
    {
    if (n > _capacity)
    {
    //cout << "reserve:" << n << endl;

    char* tmp = new char[n + 1];
    strcpy(tmp, _str);
    delete[] _str;
    _str = tmp;
    _capacity = n;
    }
    }

    void string::push_back(char ch)
    {
    if (_size == _capacity)
    {
    reserve(_capacity == 0 ? 4 : _capacity * 2);
    }

    _str[_size] = ch;
    ++_size;
    _str[_size] = '\\0';
    }

    string& string::operator+=(char ch)
    {
    push_back(ch);
    return *this;
    }

    void string::append(const char* str)
    {
    size_t len = strlen(str);
    if (_size + len > _capacity)
    {
    // 大于2倍,需要多少开多少,小于2倍按2倍扩
    reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
    }

    strcpy(_str + _size, str);
    _size += len;
    }

    string& string::operator+=(const char* str)
    {
    append(str);
    return *this;
    }

    void string::insert(size_t pos, char ch)
    {
    assert(pos <= _size);

    if (_size == _capacity)
    {
    reserve(_capacity == 0 ? 4 : _capacity * 2);
    }

    // 挪动数据
    size_t end = _size + 1;
    while (end > pos)
    {
    _str[end] = _str[end – 1];
    –end;
    }

    _str[pos] = ch;
    ++_size;
    }

    void string::insert(size_t pos, const char* s)
    {
    assert(pos <= _size);

    size_t len = strlen(s);
    if (_size + len > _capacity)
    {
    // 大于2倍,需要多少开多少,小于2倍按2倍扩
    reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
    }

    size_t end = _size + len;
    while (end > pos + len – 1)
    {
    _str[end] = _str[end – len];
    –end;
    }

    for (size_t i = 0; i < len; i++)
    {
    _str[pos + i] = s[i];
    }

    _size += len;
    }

    void string::erase(size_t pos, size_t len)
    {
    assert(pos < _size);

    if (len >= _size – pos)
    {
    _str[pos] = '\\0';
    _size = pos;
    }
    else
    {
    for (size_t i = pos + len; i <= _size; i++)
    {
    _str[i – len] = _str[i];
    }

    _size -= len;
    }
    }

    size_t string::find(char ch, size_t pos)
    {
    assert(pos < _size);

    for (size_t i = pos; i < _size; i++)
    {
    if (_str[i] == ch)
    {
    return i;
    }
    }

    return npos;
    }

    size_t string::find(const char* str, size_t pos)
    {
    assert(pos < _size);

    const char* ptr = strstr(_str + pos, str);
    if (ptr == nullptr)
    {
    return npos;
    }
    else
    {
    return ptr – _str;
    }
    }

    string string::substr(size_t pos, size_t len)
    {
    assert(pos < _size);

    // len大于剩余字符长度,更新一下len
    if (len > _size – pos)
    {
    len = _size – pos;
    }

    string sub;
    sub.reserve(len);
    for (size_t i = 0; i < len; i++)
    {
    sub += _str[pos + i];
    }

    return sub;
    }

    bool operator<(const string& s1, const string& s2)
    {
    return strcmp(s1.c_str(), s2.c_str()) < 0;
    }

    bool operator<=(const string& s1, const string& s2)
    {
    return s1 < s2 || s1 == s2;
    }

    bool operator>(const string& s1, const string& s2)
    {
    return !(s1 <= s2);
    }

    bool operator>=(const string& s1, const string& s2)
    {
    return !(s1 < s2);
    }

    bool operator==(const string& s1, const string& s2)
    {
    return strcmp(s1.c_str(), s2.c_str()) == 0;
    }

    bool operator!=(const string& s1, const string& s2)
    {
    return !(s1 == s2);
    }

    ostream& operator<<(ostream& out, const string& s)
    {
    for (auto ch : s)
    {
    out << ch;
    }

    return out;
    }

    istream& operator>>(istream& in, string& s)
    {
    s.clear();

    const int N = 256;
    char buff[N];
    int i = 0;

    char ch;
    //in >> ch;
    ch = in.get();
    while (ch != ' ' && ch != '\\n')
    {
    buff[i++] = ch;
    if (i == N – 1)
    {
    buff[i] = '\\0';
    s += buff;

    i = 0;
    }

    //in >> ch;
    ch = in.get();
    }

    if (i > 0)
    {
    buff[i] = '\\0';
    s += buff;
    }

    return in;
    }
    }

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 《STL string 底层复刻:动态数组、拷贝控制与性能优化》
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!