C++ 多次分配的成本有多大?

Ash*_*nxy 1 c++ string

我想知道实用函数中内存分配过程的成本有多大。例如下面的实现有很大的区别吗?

string method_A (string inp) {
   auto        num_fillers = inp.length() - 4;
   string filler(num_fillers, '-');
   string res = filler + inp.substr(num_fillers);
   return res;
}

string method_B (string inp) {
  const int expect_len =4;
  auto        num_fillers = inp.length() - expect_len;
  string res;
  res.reserve(num_fillers + expect_len);
  res.assign(num_fillers, '-');
  res+= inp.substr(num_fillers);
  return res;
}
Run Code Online (Sandbox Code Playgroud)

使用 method_B 代替 method_A 有什么好处吗?各自的优点和缺点是什么?

分配一次内存并用“+=”操作填充字符串是否比method_A中的做法有更好的性能?

pad*_*ddy 5

分配确实产生开销,并且在实际情况下最好避免不必要的开销。但除非必要,否则不会以牺牲可维护性/复杂性为代价。所以你应该始终权衡这一点。

对于标准库来说,没有realloc等效的。附加到动态容器通常涉及分配、复制和删除(忽略小字符串优化和预先保留的容量)。如果您在程序中经常这样做,您可能需要考虑内存碎片的可能性。

就您而言,您正在进行大量分配。

方法一:

  1. string inp参数按值传递
  2. filler构造函数分配另一个字符串
  3. inp.substr(num_fillers)分配另一个字符串
  4. operator+分配另一个字符串

方法B(目前充满错误):

  1. string inp参数按值传递
  2. res.reserve(num_fillers + expect_len)分配另一个字符串
  3. inp.substr(num_fillers)分配另一个字符串

所以,情况并没有好多少。您避免了一项分配,但仍然进行了三项分配。分配较少的方法(基于您在 中的尝试method_B)将是:

std::string method_C(const std::string& inp)
{
  const std::size_t expect_len = 4;
  const std::size_t num_fillers = inp.size() - std::min(inp.size(), expect_len);
  std::string res;
  res.reserve(num_fillers + expect_len);
  res.assign(num_fillers, '-');
  res.append(inp.begin() + num_fillers, inp.end());
  return res;
}
Run Code Online (Sandbox Code Playgroud)

上面只执行了一次分配。

append如果您确实喜欢使用,则substr可以使用以下替代方法std::string_view

  res += std::string_view(inp).substr(num_fillers);
Run Code Online (Sandbox Code Playgroud)