在不复制的情况下为字符串使用外部缓冲区

时间:2015-09-21 19:24:24

标签: c++ string c++11 string-view

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

void foo(const string& s);

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

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

foo(string(buffer, n));

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

我必须提到我不确定副本是否发生,但是查看constructor of string所有人都说副本会发生。我不知道编译器优化是否可以理解这种情况,我找不到确定副本是否发生的方法。

有没有办法为字符串使用外部缓冲区,或者至少是确保复制发生与否的方法。我目前正在使用std string和c ++ 11。

2 个答案:

答案 0 :(得分:7)

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

foo(buffer);

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

void foo(char const*)

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

图书馆基础知识技术规范包含一个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);
}

Live Example(在C ++ 14模式下需要libstdc ++ 4.9或更高版本)。

答案 1 :(得分:3)

不,error: wrong number of template arguments (2, should be at least 0) std::cout << x << '\t' << foo<std::sin, std::asin>(x) << std::endl; ^ 管理其缓冲区。您不能使用外部缓冲区的字符串。在您执行std::string时,您的示例并不意味着您的字符串实例将拥有您的string(buffer, n)并将其用作字符串,相反,它只会复制buffer的内容到它的内部缓冲区。