来自向量<string>的c_str()结果在libc++中变成垃圾

Mat*_*ain 4 c++ string garbage-collection vector

我试图弄清楚为什么以下 C++ 代码在 libstdc++ 中运行良好,但在 libc++ 中结果却c_str()变得垃圾。

该代码只是使用 构建一个字符串向量savedstrings.push_back("blah"),并且在将每个字符串添加到该向量后,立即savedstrings.back().c_str()将其添加到一个单独的向量const char*

所以每个const char*应该指向savedstrings向量中相应的字符串。这对于 libstdc++ 来说工作得很好,但是对于 libc++ 来说,随着后面的向量的添加,向量const char*开头的cstrs向量开始变成垃圾。

我不确定我是否明白这里发生了什么。savedstrings添加新字符串时向量是否会移动较早的字符串,从而使c_str()结果无效?我怎样才能阻止这种情况发生?

vector<string> savedstrings;
vector<const char*> cstrs;

for (int i = 0; i < 10; i++) {
  savedstrings.push_back("blah");
  cstrs.push_back(savedstrings.back().c_str());
}

vector<string>::iterator si;
for(si=savedstrings.begin();si!=savedstrings.end();++si)
  cout << *si << endl;

vector<const char*>::iterator ci;
for(ci=cstrs.begin();ci!=cstrs.end();++ci)
  cout << *ci << endl;
Run Code Online (Sandbox Code Playgroud)

jua*_*nza 6

如果在 中进行任何重新分配savedstrings,则指向基础字符串数据的指针可能会变得无效。取消引用此类指针将产生未定义的行为

您可以通过保留适量的容量来避免重新分配:

vector<string> savedstrings;
savedstrings.reserve(10);
Run Code Online (Sandbox Code Playgroud)

下面的示例显示了当您将元素推入 is 时向量的容量如何增长(某些 ubuntu x86_64 上的 g++ 4.7.3):

#include <vector>
#include <iostream>

int main()
{
  std::vector<int> v;

  for (int i = 0; i < 10; ++i){
    v.push_back(0);
    std::cout << v.capacity() << std::endl;
  }
}
Run Code Online (Sandbox Code Playgroud)

输出:

1
2   # re-allocation
4   # re-allocation
4
8   # re-allocation
8
8
8
16  # re-allocation
16
Run Code Online (Sandbox Code Playgroud)