zoukankan      html  css  js  c++  java
  • 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;
        };
    }
  • 相关阅读:
    KETTLE:mongdb与mysql互传数据
    6.azkban的监控
    5.azkaban权限管理
    3.azkaban3.0测试
    2.azkaban3.0安装
    1.编译azkaban
    十六:The YARN Service Registry
    十四:Using CGroups with YARN
    十二:NodeManager
    十 Writing YARN Applications
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/9785648.html
Copyright © 2011-2022 走看看