C++ StringBuilder类

#ifndef __GTL_STRING_BUILDER_H_
#define __GTL_STRING_BUILDER_H_

/* 字符串生成模板 */

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <list>
#include <string>

/*
设计方案:
    一、这里的TLStringBuilder::_container用std::list而不是std::vector?
    官方文档上注明除非你有一个用其他容器的好理由,通常都是使用std::vector。
    优势
        1. 字符串总是会附加到一个容器的末尾。std::list允许在不需要内存再分配的情况下这样做;
      因为vector是使用一个连续的内存块实现的,每用一个就可能导致内存再分配。
        2. std::list对顺序存取相当有利,而且在m_Data上所做的唯一存取操作也是顺序的。
    劣势
        1. 模板类中提供了 Revoke() 方法,该方法在 std::list 和 std::vector性能上会产生差异,
        std::vector性能上会更高效(因为 vector 遍历最后一个元素肯定比 list要快)
    总结:之所以选用 std::list 是因为大多数场景下用户都不会使用 Revoke() 方法,因此选用 std::list
    二、TLStringBuilder到底比string优化在什么地方呢?
        std::string对象执行+操作时,会创建一个新对象,而TLStringBuilder不会创建新对象,TLStringBuilder减少了创建多个临时对象的消耗
        经过测试,c++中的string是在堆上创建字符串的,并非静态区中创建对象,所以并不会占用很多的内存,因为每个变量用完之后会释放的。
    三、注意点
        a. TLStringBuilder在多线程场景下需要加锁保护
        b. 模板类型有要求(并非任意类型,这是由std::basic_string类模板决定的),与类型定义的专用化字符串类型元素的char,
       wstring,为wchar_t, u16string为char16_t,和u32string为char32_t。
*/

namespace gtl 
{
    template <typename T>
    class TLStringBuilder
    {
        typedef std::basic_string<T> StringType;    //字符串类型
        typedef std::list<StringType> ContainerType;    //字符串容器类型
        typedef typename StringType::size_type SizeType;    //字符串长度类型
    public:
        //构造函数
        TLStringBuilder() :_container(), _length(0)
        { 
        }

        //构造函数
        explicit TLStringBuilder(const StringType &str) :_container(), _length(0)
        {
            if (str.empty())
            {
                return;
            }

            this->_container.emplace_back(str);
            this->_length += str.length();
        }

        //析构函数
        ~TLStringBuilder()
        {
            this->_container.clear();
            this->_length = 0;
        }

    public:
        //追加字符串
        TLStringBuilder & Append(const StringType &str) 
        {
            if (!str.empty())
            {
                this->_container.emplace_back(str);
                this->_length += str.length();
            }
            return *this;
        }

        //撤销最后的字符串
        TLStringBuilder & Revoke(void) 
        {
            if (!this->_container.empty())
            {
                StringType tmpStr = this->_container.back();
                this->_container.pop_back();
                this->_length -= tmpStr.length();
            }

            return *this;
        }

        //获取字符串长度
        SizeType Length(void)
        {
            return this->_length;
        }

        //追加字符串 换行
        TLStringBuilder & AppendLine(const StringType &str) 
        {
            static T CRLF[]{ 10, 0 }; // C++ 11
            StringType tmpStr;

            if (!str.empty())
            {
                tmpStr = str + CRLF;
            }
            else
            {
                tmpStr = CRLF;
            }

            this->_container.push_back(tmpStr);
            this->_length += tmpStr.length();
            
            return *this;
        }

        //追加换行
        TLStringBuilder & AppendLine(void) 
        {
            static T CRLF[]{ 10, 0 }; // C++ 11
            StringType tmpStr = CRLF;

            this->_container.push_back(tmpStr);
            this->_length += tmpStr.length();

            return *this;
        }

        //拼接字符串(IT的类型需要是迭代器类型 inputIterator )
        template<class IT>
        TLStringBuilder & Add(const IT &first, const IT &last) 
        {
            for (IT item = first; item != last; ++item)
            {
                this->Append(*item);
            }

            return *this;
        }

        //转字符串
        StringType ToString(void)
        {
            StringType tmpStr;
            unsigned char *pTmp = NULL;
            unsigned int offset = 0;

            pTmp = (unsigned char *)calloc(this->_length + 1, sizeof(T));
            assert(pTmp);

            for (auto item = this->_container.begin(); item != this->_container.end(); ++item)
            {
                memcpy(pTmp + offset, item->c_str(), item->length());
                offset += item->length();
            }

            tmpStr = (T *)pTmp;

            free(pTmp);
            pTmp = NULL;

            return tmpStr;
        }

    private:
        //禁止拷贝构造 与 赋值操作
        TLStringBuilder(const TLStringBuilder &r) {};
        TLStringBuilder & operator= (const TLStringBuilder &) {}

    private:
        ContainerType _container;
        SizeType _length;
    };
}

 

posted on 2018-10-14 11:09  寒魔影  阅读(2591)  评论(0编辑  收藏  举报

导航