4

对我的应用程序的分析表明,它在字符串分配上花费了近 5% 的 CPU 时间。在很多很多地方,我正在从 64MB 字符缓冲区制作 C++ std::string 对象。问题是,缓冲区在程序运行期间永远不会改变。我对std::string(const char *buf,size_t buflen)调用的分析是正在复制字符串,因为缓冲区可能会在字符串生成后发生变化。这不是这里的问题。有没有办法解决这个问题?

编辑:我正在处理二进制数据,所以我不能只是传递char *s. 此外,我会因为总是扫描 NULL 而产生大量开销,而这是std::string避免的。

4

5 回答 5

7

如果字符串不会改变,并且如果保证它的生命周期比你要使用的字符串长,那么不要使用std::string.

相反,考虑一个简单的 C 字符串包装器,如建议的string_ref<T>.

于 2012-10-08T16:40:07.733 回答
4

二进制数据?停止使用 std::string 并使用std::vector<char>. 但这不会解决您复制它的问题。根据您的描述,如果这个巨大的 64MB 缓冲区永远不会改变,那么您真的不应该使用 std::string 或std::vector<char>,两者都不是一个好主意。你真的应该传递一个 const char* 指针(const uint8_t* 会更描述二进制数据,但在幕后它是一样的,忽略符号问题)。传递指针和它的 size_t 长度,或者用另一个“结束”指针传递指针。如果您不喜欢传递单独的离散变量(指针和缓冲区的长度),请创建一个结构来描述缓冲区并让每个人都使用它们:

struct binbuf_desc {
    uint8_t* addr;
    size_t len;
    binbuf_desc(addr,len) : addr(addr), len(len) {}
}

binbuf_desc您始终可以通过使用对象来引用您的 64MB 缓冲区(或任何其他大小的缓冲区) 。请注意, binbuf_desc 对象不拥有缓冲区(或缓冲区的副本),它们只是它的描述符,因此您可以将它们传递到任何地方,而不必担心 binbuf_desc 会制作不必要的缓冲区副本。

于 2012-10-09T15:29:48.477 回答
3

没有便携式解决方案。如果您告诉我们您正在使用什么工具链,那么有人可能知道特定于您的库实现的技巧。但在大多数情况下,std::string析构函数(和赋值运算符)将释放字符串内容,而您不能释放字符串文字。(这不是不可能有例外,实际上小字符串优化是跳过释放的常见情况,但这些是实现细节。)

更好的方法是std::string在您不需要/想要动态分配时不使用。 const char*在现代 C++ 中仍然可以正常工作。

于 2012-10-08T16:38:40.767 回答
1

从 C++17 开始,std::string_view可能是你的方式。它既可以从一个裸 C 字符串(有或没有长度)初始化,也可以从一个std::string

但是,data() 方法返回一个以零结尾的字符串没有任何限制。

如果您需要这种“根据请求进行零终止”的行为,可以str_view使用 Adam Sawicki 等看起来令人满意的替代方法(https://github.com/sawickiap/str_view

于 2020-02-29T18:58:38.620 回答
0

似乎使用const char *而不是对std::string你来说是最好的方法。但是您还应该考虑如何使用字符串。可能会发生从 char 指针到std::string对象的隐式转换。例如,这可能发生在函数调用期间。

于 2012-10-08T16:47:36.490 回答