高效程序总是尽量避免频繁触碰在堆上分配和释放内存,所以无论是std::string
还是folly:fbstring
都做了SSO
( small string optimization )。而folly::FixedString
是一个很有意思的实现,它可以把任意长度的字符串都放在堆上。代码可见https://github.com/facebook/folly/blob/master/folly/FixedString.h。
它很类似于char[N]
,以及std::array<char, N>
。区别在于,它支持兼容std::string
的大多数 API 和运算。比如下面实例:
using namespace folly::string_literals;
auto hello = "hello"_fs; // a FixedString<5>
auto world = "world"_fs; // a FixedString<5>
auto hello_world = hello + ' ' + world + '!'; // a FixedString<12>
folly::FixedString<24> more_space = hello_world;
more_space.replace(0, 5, "my"); // more_space = "my world";
其内存布局非常简单直接:
tempalte<typename Char, size_t SIZE>
FixedString {
Char data[SIZE + 1]; // 需要多一个字节存放\0。
size_t size; // 字符串实际长度。
};
其主要实现的黑科技是std::index_sequence
,简单举个例子,它实现了从字符串地址构造一个FixedString
对象:
constexpr BasicFixedString(const Char* that, size_t count) noexcept(false)
: BasicFixedString{that, count, std::make_index_sequence<SIZE>{}}
{}
template <class That, size_t... Is>
constexpr BasicFixedString(
const That& that,
std::size_t size,
std::index_sequence<Is...>,
std::size_t pos = 0,
std::size_t count = npos) noexcept
: data_{(Is < (size - pos) && Is < count ? that[Is + pos] : Char(0))...,
Char(0)},
size_{folly::constexpr_min(size - pos, count)} {}
Q. E. D.