关于指针的STL向量的奇怪错误

时间:2013-12-28 19:51:52

标签: c++ pointers vector stl

我有一个小代码片段,会在运行时产生错误。以下代码存储mystruct的数据,并创建一个指针向量,用于存储相应数据的地址。

struct mystruct{
  std::vector < int > someinfo;
  int somenumbers;
  double *somepointer;
  double someparm;
  void Print(){....}
};

void DoSomething(mystruct &_somestruct, std::vector< mystruct > &_somevec,
         std::vector<mystruct *> &_ptr){
  _somevec.push_back(_somestruct);
  _ptr.push_back(&(_somevec.back()));
}

void ReadStruct(){
  std::vector<mystruct > _vec;
  std::vector<mystruct *> _ptr;

  for(int i=0;i<100;i++){
    mystruct _struct;

    _struct.somenumbers = 3;
    _struct.someinfo.push_back(0);
    _struct.someinfo.push_back(1);
    _struct.someinfo.push_back(2);

    DoSomething(_struct, _vec, _ptr);
  }
  _vec[0].Print(); //Prints correctly
  _ptr[0]->Print();//Prints garbage info
}

如果我首先创建向量然后创建指针向量,那么代码就可以完美地工作,即

void DoSomething(mystruct &_somestruct, std::vector< mystruct > &_somevec){
  _somevec.push_back(_somestruct);
  //_ptr.push_back(&(_somevec.back()));
}
void DoSomething1(std::vector< mystruct > &_somevec, std::vector<mystruct *> &_ptr){
  for(int i=0;i<_somevec.size();i++)
    _ptr.push_back(&(_somevec[i]));
}

我不知道我在做什么错。非常感谢您的帮助/投入!!

2 个答案:

答案 0 :(得分:2)

这对我来说看起来不太安全。

_ptr.push_back(&(_somevec.back()));中,您将获取_somevec中元素的地址。但是当_somevec被更改时,例如push_back地址无效!

例如,这不起作用:

std::vector<int> v;
v.push_back(17);
int* p = &v.back(); // pointer is valid
for(int i=0; i<10; i++) v.push_back(0);
*p = 42; // ERROR: p is no longer valid!

在使用reserve之前,您可以使用push_back来提高效率。

std::vector<int> v;
v.reserve(100); // v will now have enough room to not reallocate memory
v.push_back(17);
int* p = &v.back(); // pointer is valid
for(int i=0; i<10; i++) v.push_back(0);
*p = 42; // (probably) OK: p is still valid

但我不建议这样做。

答案 1 :(得分:1)

看起来好像是将元素插入到一个向量中并使用另一个向量的指针引用它们。但是,对于耗尽容量的对象向量并重新定位对象似乎没有任何预防措施,使所有指针无效。

验证此假设的最简单方法是查看对象向量的capacity()是否发生变化。最简单的修复可能是使用std::deque<mystruct>,因为std::deque<T>在两端添加/删除对象时不会重定位其对象。