标签:修改 [] 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。 */
标签:修改 [] poi HERE code app UNC 模板 lov
原文地址:https://www.cnblogs.com/zhanggaofeng/p/9785648.html