在恒定时间内修剪 C++ 字符串
Posted
技术标签:
【中文标题】在恒定时间内修剪 C++ 字符串【英文标题】:Trimming C++ string in constant time 【发布时间】:2019-12-07 02:10:48 【问题描述】:是否有一种 STL/库方法可以在恒定时间内减小字符串大小(修剪它)。
在 C 中,这可以通过在最后一个索引后面添加 '\0' 来在恒定时间内完成。
C++ 调整大小的复杂性未定义,很可能是 O(N)
http://www.cplusplus.com/reference/string/string/resize/
【问题讨论】:
您从哪里获得这些信息?你有什么证据表明 C 可以在恒定时间内调整字符串的大小?std::string::resize
的复杂度在形式上是O(n)
。然而,如果您在减小字符串大小时实际检查 C++ 库的实现,您会对该特定操作的实际复杂性感到非常惊讶。
是的,它是 O(n)。但它必须是,因为如果新的大小超过容量,它必须重新分配和复制。而且即使只是扩大了字符串,也必须初始化新的部分。当然,如果它没有变得更大,那么工作量是恒定的。顺便说一句:在 C++11 之前的 COW 字符串中,它必须是 O(n),在任何情况下都会由于修改而发生不共享。
【参考方案1】:
@SamVarshavchik 在 cmets 中很腼腆,但值得一提的是:在包括 libstdc++ 在内的许多实现中,std::string::resize()
将通过减少字符串的长度而不是重新分配 / 在恒定时间内减小字符串的大小/复制数据:
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/basic_string.tcc 。 O(n) 的估计是如果你增加大小,强制重新分配和复制字符串。
另外,在 C++17 中,std::string_view
是粗略的不可变对应物,相当于通过敲击空字节来“修剪”C 字符串。它需要一个字符串的切片(指针 + 大小)而不复制其内容,然后您可以将它传递给各种 STL 函数或从流中打印它。
std::string hello_world = "hello world";
auto hello = std::string_view(hello_world.data(), 5);
std::cout << hello; // prints hello
需要注意的是 string_view 不拥有数据,因此一旦原始字符串超出范围,您将无法使用它,并且您不想以可能导致它的方式修改原始字符串重新分配。
【讨论】:
【参考方案2】:C++17的方式,我们可以在O(1)内实现substr操作。
https://www.modernescpp.com/index.php/c-17-avoid-copying-with-std-string-view
std::string_view
也不要为大字符串分配堆内存。
std::string
在堆上分配内存,但 std::string
的例外情况是,MSVC 和 GCC 的大小为 15,Clang 的大小为 23。 std::string
上述大小未在堆上分配内存。
【讨论】:
以上是关于在恒定时间内修剪 C++ 字符串的主要内容,如果未能解决你的问题,请参考以下文章