76

什么是最有效的前置方式std::string?是否值得写出整个函数来这样做,还是只需要 1 - 2 行?我没有看到任何与std::string::push_front.

4

4 回答 4

106

实际上有一个与不存在类似的功能std::string::push_front,请参见下面的示例。


std::string::insert 的文档

#include <iostream>
#include <string>

int
main (int argc, char *argv[])
{
  std::string s1 (" world");
  std::string s2 ("ello");

  s1.insert (0,     s2); // insert the contents of s2 at offset 0 in s1
  s1.insert (0, 1, 'h'); // insert one (1) 'h'        at offset 0 in s1

  std::cout << s1 << std::endl;
}

输出:

hello world

由于在字符串前面添加数据可能需要重新分配和复制/移动现有数据,您可以通过使用std::string::reserve(预先分配更多内存)摆脱重新分配部分来获得一些性能优势。

遗憾的是,数据的复制/移动是不可避免的,除非您定义自己的自定义类,该类的行为类似于std::string分配一个大缓冲区并将第一个内容放在此内存缓冲区的中心。

然后,如果缓冲区足够大,您可以在不重新分配和移动数据的情况下预先添加和附加数据。但是,显然仍然需要从复制到目标。


如果你有一个缓冲区,你知道你会更频繁地预先添加数据而不是添加一个好的替代方法是向后存储字符串,并在需要时将其反转(如果这种情况更罕见)。

于 2011-12-12T00:24:07.753 回答
13
myString.insert(0, otherString);

让标准模板库的编写者担心效率;利用他们所有的工作时间,而不是重新编程轮子。

这种方式可以做到这两点。

只要您使用的 STL 实现经过深思熟虑,您就会拥有高效的代码。如果您使用的是写得不好的 STL,那么无论如何您都会遇到更大的问题 :)

于 2014-01-27T11:11:15.013 回答
7

如果您正在使用std::string::append,您应该意识到以下是等效的:

std::string lhs1 = "hello ";
std::string lhs2 = "hello ";
std::string rhs = "world!";

lhs1.append(rhs);
lhs2 += rhs; // equivalent to above
// Also the same:
// lhs2 = lhs2 + rhs;

同样,“前置”将等同于以下内容:

std::string result = "world";
result = "hello " + result;
// If prepend existed, this would be equivalent to
// result.prepend("hello");

您应该注意到,尽管执行上述操作是相当低效的。

于 2011-12-12T00:18:39.090 回答
3

有一个重载string operator+ (char lhs, const string& rhs);,所以你只能做your_string 'a' + your_string模仿push_front

这不是就地的,而是创建了一个新字符串,所以不要指望它是有效的。对于(可能)更有效的解决方案,用于resize收集空间,std::copy_backward将整个字符串向后移动一个并在开头插入新字符。

于 2011-12-12T00:18:25.153 回答