首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >连接字符串的C++最佳实践

连接字符串的C++最佳实践
EN

Stack Overflow用户
提问于 2018-07-10 16:26:40
回答 2查看 5.2K关注 0票数 0

如果频繁地连接字符串以形成最终结果,那么最好的做法是什么?( C++11或更高版本)

那么string::append()ostringstream呢?

还有另一个问题:如果我使用许多+连接字符串,现代编译器会以最有效的方式优化它吗?(就像Java现在可以使用StringBuilder优化字符串连接一样)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-10 18:02:44

万一你在人为的领域里想到了StringBuilder。

您可以使用字母表(Google)库,ABCLib,ABCL或只是ABCL。

https://abseil.io/docs/cpp/guides/strings向前看并立即分配它所需的一切,然后按照您的需要在其中构建字符串。对于concat作业,只需要absl::StrCat()和absl::StrAppend()。

我不擅长解释事情。也许下面这个https://godbolt.org/g/V45pXJ链接可能比我讲得更好。

/g/V45pXJ

了解更多关于YouTube:https://www.youtube.com/watch?v=xu7q8dGvuwk&t=32m (ffw到32分钟)的信息

youtube.com/watch?v=xu7q8dGvuwk&t=32m

代码语言:javascript
复制
#include <string>
#include <iostream>
#include <absl/strings/str_cat.h>

int main()
{
    std::string s1,s2,s3,s4,
                s5,s6,s7,s8,
                s9,s10,s11,s12;
    std::getline(std::cin, s1);
    std::getline(std::cin, s2);
    std::getline(std::cin, s3);
    std::getline(std::cin, s4);
    std::getline(std::cin, s5);
    std::getline(std::cin, s6);
    std::getline(std::cin, s7);
    std::getline(std::cin, s8);
    std::getline(std::cin, s9);
    std::getline(std::cin, s10);
    std::getline(std::cin, s11);
    std::getline(std::cin, s12);
    std::string s = s1 + s2 + s3 + s4 +  // a call to operator+ for each +
                    s5 + s6 + s7 + s8 +
                    s9 + s10 + s11 + s12;

    // you shall see that
    // a lot of destructors get called at this point
    // because operator+ create temporaries

    std::string abseil_s = 
       absl::StrCat(s1,s2,s3,s4,  // load all handles into memory
                    s5,s6,s7,s8,  // then make only one call!
                    s9,s10,s11,s12);

    return s.size() + abseil_s.size();

    // you shall see that
    // only "real" s1 - s12 get destroyed
    // at these point
    // because there are no temporaries!

}

更新2021

现在,您也可以在fmt:formatstd::format实现完成时使用c++20 图书馆。(当前的fmtlib现在将支持插入到c++14。)

format会像The StrCat那样向前看,所以不会浪费时间。

代码语言:javascript
复制
    string fmt_s = 
        fmt::format("{}{}{}{}{}{}{}{}{}{}{}{}",
                    s1,s2,s3,s4,  // load all handles into memory
                    s5,s6,s7,s8,  // then make only one call!
                    s9,s10,s11,s12);

[活着]

票数 3
EN

Stack Overflow用户

发布于 2018-07-10 16:34:03

如果您不需要std::ostringstream的任何特性,那么如果您的最终目标是获得单个std::string (事先充分调用reserve可能会减少一些无用的分配),那么向同一个字符串添加普通字符串通常是最有效的方法。在内部,std::ostringstream的工作方式大致相同,但它为额外的层增加了一些开销。

还有另一个问题:如果我使用许多+连接字符串,现代编译器会以最有效的方式优化它吗?(就像Java现在可以使用StringBuilder优化字符串连接一样)

std::string已经有点像StringBuilder了,因为它是一种有效增长的可变类型,因此您不需要为此使用不同的类型。

现在,在C++03中,多个级联的+将创建所有相关的临时字符串,因此如果要保持效率,就必须在目标字符串上显式地使用+=

OTOH,C++11添加了带有rvalue引用的operator+重载,这允许为下一次连接回收/扩展临时字符串的分配存储空间,因此在大多数情况下效率应该是可比的--感谢@Daniel指出了这一点。

我认为有一种情况是这样的,那就是:

代码语言:javascript
复制
big_string += a + b + c;

在这种情况下,a + b + c本身是高效计算的,但是没有考虑到它将被附加到另一个字符串(因此,可能没有任何额外的分配)。你最好还是用“传统”方法,或者用

代码语言:javascript
复制
big_string = std::move(big_string) + a + b + c;
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51270175

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档