#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; }; }