Abseil之字符串连接

当代码reviower人说:“不要使用字符串连接操作符,它不是那么高效”时,用户常常感到惊讶。std::string::operator+不高效?搞错了吧?

事实证明,这样的低效率并不是显而易见的。实际上,这两个代码段的执行时间几乎相同:

std::string foo = LongString1();
std::string bar = LongString2();
std::string foobar = foo + bar;

std::string foo = LongString1();
std::string bar = LongString2();
std::string foobar = absl::StrCat(foo, bar);

 但是,这两个片段的情况并非如此:

std::string foo = LongString1();
std::string bar = LongString2();
std::string baz = LongString3();
string foobar = foo + bar + baz;

std::string foo = LongString1();
std::string bar = LongString2();
std::string baz = LongString3();
std::string foobar = absl::StrCat(foo, bar, baz);

 当我们把foo+bar+baz表达式中发生的事情分开时,可以理解这两种情况不同的原因。因为C++中没有三个参数操作符的重载,所以这个操作必然会对String::在这两个调用之间,操作将构造(和存储)一个临时字符串。所以STD::字符串foobar = foo + bar + baz确实等价于:

std::string temp = foo + bar;
std::string foobar = std::move(temp) + baz;

 具体来说,请注意,在将foo和bar的内容放入foobar之前,必须将它们复制到临时位置。C++ 11至少允许第二个级联发生,而不需要创建一个新的std::move(temp) + baz。但是,最初为临时文件分配的缓冲区可能不够大,无法容纳最后一个字符串,在这种情况下,需要重新分配(和另一个副本)。因此,在最坏的情况下,N个字符串连接链需要O(N)重新分配

最好使用absl::StrCat()absl/strings/str_cat.h是一个很好的助手函数,它计算必要的字符串长度,保留该大小,并将所有输入数据连接到输出中—一个优化良好的O(n)。同样,对于以下情况:

foobar += foo + bar + baz;

 使用absl::StrAppend(),它执行类似的优化:

absl::StrAppend(&foobar, foo, bar, baz);

 此外,absl::StrCat()absl::StrAppend()对字符串类型以外的类型进行操作,可以使用absl::StrCat/absl::StrAppend转换为int32_t, uint32_t, int64_t, uint64_t, float, double, const char*, 和string_view,如下所示:

 

std::string foo = absl::StrCat("The year is ", year);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值