【问题标题】:Can I achieve linear (or close to) complexity concatenating strings without allocation?我可以在不分配的情况下实现线性(或接近)复杂性连接字符串吗?
【发布时间】:2015-08-04 15:28:48
【问题描述】:
{
   std::string s = "this is a string ";
   std::string res = std::string();
   int sLength = s.length();
   for(int i = 0; i < sLength; i++)
      res += s[i];
}

我想这个 C++ 的复杂度是严格线性的(关于字符分配),而不是 C# 中等价物的二次复杂度。

但是,在这种情况下,没有预先分配内存,我们实际上是否也在考虑二次复杂度?如果是,分配一个 char 数组是否有助于我们实现线性复杂度?

【问题讨论】:

  • 我不确定我是否理解您的问题?您是否认为每个连接都会强制分配另一个size = previous_size + 1?这不是它的工作原理。
  • 1.字符串生成器。 2. 在 C# 中,这将占用相同数量的内存。 GC 会吃掉所有的额外分配
  • @CoryKramer 我至少认为这是一种可能性。
  • @AK_ 所以你说 C++ 和 C# 的实现都是二次的。
  • @Franklin No. 两者都是线性的。出于不同的原因。

标签: c# c++ string


【解决方案1】:

根据cppr,将字符添加到字符串具有恒定的复杂性(尽管我认为这带有隐含的“摊销”,如string::push_back)。

所以你的代码已经具有线性复杂度了。

如果您关心分配成本并且事先有大小的上限,您也可以只reserve 足够的空间来避免任何重新分配和复制字符串。然后,即使是普通的 char 缓冲区也不应该超过你的表现(显着)。

【讨论】:

  • +1 ;谢谢。因此,虽然有/没有“保留”都提供线性复杂性,但“保留”会显示出微小的实际改进。
  • @Franklin 是否微小有待衡量,但复杂度是一样的。
【解决方案2】:

您可以通过调用std::string::reserve 来实现线性复杂度。这将防止随着字符串的增长而重新分配:

std::string s = "this is a string ";
std::string res = "what is this? ";
res.reserve(s.length() + res.length());

for(int i = 0; i < s.length(); i++)
   res += s[i];

显然你不会在现实生活中像这样连接字符串。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-04
    • 2023-03-05
    • 2019-01-16
    • 2019-11-23
    • 1970-01-01
    • 1970-01-01
    • 2021-05-16
    相关资源
    最近更新 更多