3

假设我有一个const string&作为输入的函数,例如:

void foo(const string& s);

然后我有一个内部缓冲区const char* buffer;,我知道它的大小。

我想如果我创建内联字符串,仍然会发生一个副本:

foo(string(buffer, n));

但是没有必要复制缓冲区,因为所有东西都是不变的,我只需要字符串类的功能而不是它创建的缓冲区。

我必须提到,我不确定是否发生了复制,但是查看字符串的构造函数,他们都说会发生复制。我不知道编译器优化能否理解这种情况,我也找不到方法来确定是否发生了复制。

有什么方法可以为字符串使用外部缓冲区,或者至少有一种方法可以确保复制发生与否。我目前正在使用 std 字符串和 c++11。

4

2 回答 2

7

是的,复制总是在发生。顺便说一句,您不需要包装std::string(buffer),因为构造函数std::string(char const*)是隐式且简单的

foo(buffer);

将隐式地将缓冲区复制到字符串中。如果您是作者,foo则可以添加重载

void foo(char const*)

这避免了复制。strtok但是,C 字符串存在空终止符是字符串 API 的一部分的问题,因此在不改变底层字符串 (a la )的情况下,您无法轻松创建子字符串。

Library Fundamentals Technical Specification 包含一个string_view类,该类将消除类似的复制char const*,但保留 的子集功能std::string

#include <iostream>
#include <experimental/string_view>

void foo(std::experimental::string_view v) { std::cout << v.substr(2,8) << '\n'; }

int main()
{
    char const* buffer = "war and peace";
    foo(buffer);
}

实时示例(在 C++14 模式下需要 libstdc++ 4.9 或更高版本)。

于 2015-09-21T20:06:47.920 回答
3

不,std::string管理它的缓冲区。你不能有一个使用外部缓冲区的字符串。在您执行此操作时的示例中,string(buffer, n)这并不意味着您的字符串实例将拥有您的buffer并将其用作字符串,而是将其内容复制buffer到其内部缓冲区。

于 2015-09-21T19:54:31.320 回答