【问题标题】:c++14 - Is this a good way to prepend a char on a string?c++14 - 这是在字符串上添加字符的好方法吗?
【发布时间】:2018-12-14 10:32:16
【问题描述】:

如果我想将 char c 添加到字符串 s 的开头,以下是好的做法吗?

string s = "oo";
char c = 'f';
s = c + s;

在关于 SO 的问题“Prepend std::string”中,建议这样做的答案不如建议使用成员函数 .insert() 的最佳答案受欢迎。

除了效率还有其他原因吗(s = c + s效率不高,string s的所有内容都必须复制)?

【问题讨论】:

  • 它可能效率不高,但插入与向前移动其他内容相比,没有办法实现这一点。你甚至可以说这有点快,因为它不必检查是否在第一个字符之前移动字符
  • @Athosvk:尽管除非它由 SSO 处理,否则使用 + 将始终需要分配一个缓冲区。
  • 效率参数基本上就是这样:你的添加+分配了一个不必要的临时对象(至少在gcc/clang下,生成的程序集真的很丑)。但请注意,例如c + std::move(s) 可以等同于使用insert()insert() 可能仍然需要重新分配内部字符串缓冲区(假设不涉及小字符串优化),因此无论哪种方式都不会赢得太多。这不太可能成为问题,因此请继续解决更重要的问题:)
  • @amon Imo 这是一个很好的答案。你为什么把它作为评论发布?
  • @besc 写一个好的答案比写评论更难。此外,我不会为我投票结束的问题写答案。为什么我关门了?该站点的范围更多地是关于软件工程概念和设计级别的问题。这个问题显然是代码级别的,这样的问题更适合 Stack Overflow。

标签: c++ string performance c++14


【解决方案1】:

既然两者都执行相同的操作,那么除了效率之外,还有什么原因? c+s 将创建一个临时字符串,因此需要复制cs 中的每个字符,并且可能需要堆分配。然后临时对象将被移动到给定对象中,该对象将释放其当前内存(如果有)。这些操作并不便宜。

相比之下,insert在新字符容量不足时执行堆分配。您仍然可以进行复制,因为您是在开头插入的。但仅此而已。它与在连续数组的头部插入一样有效。

【讨论】:

    【解决方案2】:

    s = c + s 操作会创建一个临时对象,可能会在堆上动态分配内存。执行所需的追加操作,然后将其复制回字符串变量。涉及更多的指令和内存操作。

    诸如分配和取消分配内存之类的内存操作成本很高。 仅当没有足够的连续内存可用于字符串时,插入才会重新分配内存。在最坏的情况下,它仍然会匹配 s = c + s 方法。

    虽然这不是什么性能问题(考虑到最坏的情况),但从程序员的角度来看,它更加优雅且易于理解。

    【讨论】:

      【解决方案3】:

      还要注意,没有什么可以阻止字符串的实现允许在两端进行有限的追加,而无需移动内容。默认实现不这样做,但某些实现可能会在您第一次前置时在字符串的前面保留额外的空间,以便后续前置是“免费的”。有一些矢量实现可以做到这一点。

      【讨论】:

        猜你喜欢
        • 2010-11-01
        • 2012-05-24
        • 2014-06-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多