码迷,mamicode.com
首页 > 编程语言 > 详细

C++ StringBuilder类

时间:2018-10-14 13:59:59      阅读:550      评论:0      收藏:0      [点我收藏+]

标签:修改   []   poi   HERE   code   app   UNC   模板   lov   

#ifndef __GTL_STRINGBUILDER_H_
#define __GTL_STRINGBUILDER_H_

#include <list>
#include <string>

namespace gtl 
{
    /* 字符串拼接类 */
    template <typename chr>
    class TLStringBuilder {
    private:
        typedef std::basic_string<chr> string_t;
        typedef std::list<string_t> container_t; // Reasons not to use vector below.
        //typename标志string_t::size_type是一个类型,并非属性
        typedef typename string_t::size_type size_type; // Reuse the size type in the string.
        container_t _container;
        size_type _total_size;
        void append(const string_t &src)
        {
            _container.push_back(src);
            //+=意味着_total_size必须初始化
            _total_size += src.size();
        }

    private:
        // No copy constructor, no assignment.
        TLStringBuilder(const TLStringBuilder &);
        TLStringBuilder & operator= (const TLStringBuilder &);

    public:
        TLStringBuilder(const string_t &src)
        {
            if (!src.empty()) {
                _container.push_back(src);
            }
            _total_size = src.size();
        }

        TLStringBuilder()
        {
            _total_size = 0;
        }

        ~TLStringBuilder()
        {
            _container.clear();
            std::list<string_t>().swap(_container);
            _total_size = 0;
        }

    public:
        // TODO: Constructor that takes an array of strings.
        //支持链式编程
        TLStringBuilder & Append(const string_t &src) {
            append(src);
            return *this; // allow chaining.
        }

        //类模板内部模板函数的定义方式
        // This one lets you add any STL container to the string builder.
        template<class inputIterator>
        TLStringBuilder & Add(const inputIterator &first, const inputIterator &afterLast) {
            // std::for_each and a lambda look like overkill here.
            // <b>Not</b> using std::copy, since we want to update m_totalSize too.
            for (inputIterator f = first; f != afterLast; ++f) {
                append(*f);
            }
            return *this; // allow chaining.
        }

        TLStringBuilder & AppendLine(const string_t &src) {
            //10是ascii码,表示换行
            //这里是定义一个数组,有两个元素 { 10, 0 }
            static chr lineFeed[]{ 10, 0 }; // C++ 11
            _container.push_back(src + lineFeed);
            _total_size += 1 + src.size();
            return *this; // allow chaining.
        }
        TLStringBuilder & AppendLine() {
            static chr lineFeed[]{ 10, 0 };
            _container.push_back(lineFeed);
            _total_size++;
            return *this; // allow chaining.
        }

        // TODO: AppendFormat implementation. Not relevant for the article.

        // Like C# StringBuilder.ToString()
        // Note the use of reserve() to avoid reallocations.
        string_t ToString() const {
            string_t result;

            // The whole point of the exercise!
            // If the container has a lot of strings, reallocation (each time the result grows) will take a serious toll,
            // both in performance and chances of failure.
            // I measured (in code I cannot publish) fractions of a second using ‘reserve‘, and almost two minutes using +=.
            //避免每次追加字符串都要分配内存
            result.reserve(_total_size + 1);
            // result = std::accumulate(m_Data.begin(), m_Data.end(), result); // This would lose the advantage of ‘reserve‘
            /*
                注意:此处的iter的类型为什么是const_iterator而不是iterator
                这是因为ToString()被const修饰了,c++编译器禁止在函数内修改类属性
            */
            for (std::list<string_t>::const_iterator iter = _container.begin(); iter != _container.end(); ++iter) {
                result += *iter;
            }
            return result;
        }

        //暂时无需支持join
        //// like javascript Array.join()
        //string_t Join(const string_t &delim) const {
        //    if (delim.empty()) {
        //        return ToString();
        //    }
        //    string_t result;
        //    if (m_Data.empty()) {
        //        return result;
        //    }
        //    // Hope we don‘t overflow the size type.
        //    size_type st = (delim.size() * (m_Data.size() - 1)) + m_totalSize + 1;
        //    result.reserve(st);
        //    // If you need reasons to love C++11, here is one.
        //    struct adder {
        //        string_t m_Joiner;
        //        adder(const string_t &s) : m_Joiner(s) {
        //            // This constructor is NOT empty.
        //        }
        //        // This functor runs under accumulate() without reallocations, if ‘l‘ has reserved enough memory.
        //        string_t operator()(string_t &l, const string_t &r) {
        //            l += m_Joiner;
        //            l += r;
        //            return l;
        //        }
        //    } adr(delim);
        //    auto iter = m_Data.begin();
        //    // Skip the delimiter before the first element in the container.
        //    result += *iter;
        //    return std::accumulate(++iter, m_Data.end(), result, adr);
        //}

    };
}

#endif
/*
说明一:stringbuilder到底比string优化在什么地方呢?
    优化在于string对象执行+操作时,会创建一个新对象,
而stringbuilder不会创建新对象,stringbuilder减少了创建多个临时对象的消耗
*/
/*
说明二:
    经过测试,c++中的string是在堆上创建字符串的,并非静态区中创建对象,
所以并不会占用很多的内存,因为每个变量用完之后会释放的。
*/
/*
说明三:这里的TLStringBuilder::_data用std::list而不是std::vector?
    官方文档上注明除非你有一个用其他容器的好理由,通常都是使用std::vector。
这里有两个原因
1. 字符串总是会附加到一个容器的末尾。std::list允许在不需要内存再分配的情况下这样做;
因为vector是使用一个连续的内存块实现的,每用一个就可能导致内存再分配。
2. std::list对顺序存取相当有利,而且在m_Data上所做的唯一存取操作也是顺序的。
*/
/*
注意1:stringbuilder用于多线程时,需要加锁,但是什么变量用于多线程时不需要加锁呢?
注意2:模板类型有要求(并非任意类型,这是由std::basic_string类模板决定的):
    与类型定义的专用化字符串类型元素的char, wstring,为wchar_t, u16string为char16_t,和u32string为char32_t。
*/

 

C++ StringBuilder类

标签:修改   []   poi   HERE   code   app   UNC   模板   lov   

原文地址:https://www.cnblogs.com/zhanggaofeng/p/9785648.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!