【问题标题】:Construct std::string from up to X characters, stopping at null char从最多 X 个字符构造 std::string,在 null char 处停止
【发布时间】:2015-09-09 16:54:04
【问题描述】:

我正在从文件中的结构中读取字符串,其中每个字符串具有固定长度,并带有'\0' 填充。如果存储的字符串需要整个长度,则它们不是以零结尾的。

我目前正在用这样的方式构建std::strings:

// char MyString[1000];
std::string stdmystring(MyString, ARRAYSIZE(MyString));

但是,这也会复制填充。我现在可以修剪字符串,但有没有一种优雅而快速的方法来防止复制?

速度比空间更重要,因为它是循环运行的。

【问题讨论】:

  • 您可以使用 POSIX strnlen 来确定大小。 (你应该这样做,否则 string::size() 总是数组大小)
  • 没错,绝对是优化。如果没有人提出如何在没有第二个循环来确定大小的情况下执行此操作(这是我的想法......),我将使用它。

标签: c++ stdstring c++03


【解决方案1】:

简单的解决方案是:

  1. 先计算正确的长度

    • 按照 Dieter 的建议使用 strnlen
    • std::find(MyString,MyString+ARRAYSIZE(MyString),'\0') 哪个 IME 不会更慢

    请注意,如果您的字符串适合缓存,这可能会主导额外的循环成本

  2. 保留最大字符串大小(您确实说过空间不太重要),并编写一个循环附加字符,直到用尽宽度或达到 nul(如 copy_until

  3. 实际上创建一个用 nuls 初始化的 max-size 字符串,将strncpy 放入其中,如果您希望大小正确,可以选择擦除unused nuls

第二个选项只使用一个循环,而第三个在概念上使用两个(它在字符串 ctor 中,然后在副本中)。但是,每个字符的 push_back 似乎比简单的字符分配更昂贵,所以如果 #3 在现实中更快,我不会感到惊讶。配置文件并查看!

【讨论】:

  • 至少在 Visual Studio 中,已知大小的字符串构造使用 memcpy 并且比其他任何方法都快,所以我将采用 Dieter 的方法。
【解决方案2】:

如果大小不是问题,一种可能的方法是创建一个空的std::string,然后使用reserve() 预分配可能需要的空间,然后添加每个字符,直到遇到'\0'

std::string stdmystring;
stdmystring.reserve(MyString_MAX_SIZE) ;
for(size_t i=0;i<MyString_MAX_SIZE && MyString[i]!='\0';++i);
stdmystring+=MyString[i];

reserve() 保证你分配一个内存,因为你知道 max_size 并且字符串永远不会变得比这更大。

对 += 运算符函数的调用可能会被内联,但它仍然必须检查字符串是否具有所需的容量,这在您的情况下是浪费的。事实上,这可能与简单地使用 strlen 首先找到字符串的确切长度相同或更糟,因此您必须对其进行测试。

【讨论】:

  • 稍后我将不得不研究一些std::string 实现,但我认为reserve 可能是一个悲观:它可能会阻止小字符串优化,这可能对OP 的情况,取决于平均和字符串长度。
  • 是的,这是真的,但这取决于具体情况。短字符串必须适合用于长字符串的大小、容量和指针的空间,以及长字符串各自的大小和一些标志位,以区分短字符串和长字符串。通常短字符串容量仅比 3 个机器字短一点。如果平均字符串大小可以适合该 reserve() 确实会对性能不利,但如果有很多足够长的字符串,由于多次分配和复制,首先不保留可能会更糟。
【解决方案3】:

我认为最直接的方法是将您的内部MyString 数组过度分配一个字节,始终为空终止最后一个字节,并使用std::string 的C 字符串构造函数。 (请记住,您的进程很可能是文件上的 I/O 绑定,因此 C 字符串构造函数使用的任何算法都应该没问题)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-10
    • 2015-04-26
    • 2016-04-04
    • 2013-01-23
    • 2020-08-20
    • 2012-05-08
    • 1970-01-01
    相关资源
    最近更新 更多