【问题标题】:Strange error regarding STL vector of pointers关于 STL 指针向量的奇怪错误
【发布时间】:2013-12-28 19:51:52
【问题描述】:

我有一个小代码 sn-p 在运行时会产生错误。以下代码存储 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]));
}

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

【问题讨论】:

  • 请缩进您的代码以使其可读。谢谢。
  • 指针版本是未定义的行为,因为_struct 超出范围并在每次循环迭代后被破坏,非指针版本通过复制结构来工作。
  • @Mgetz 但它不是存储在 _somevec 中吗?我正在存储 _somevec 的地址。
  • @SumanVajjala no, _somevec 存储一个副本而不是原始结构,如果您打算存储一个指针,您应该使用new在堆上显式分配它

标签: c++ pointers vector stl


【解决方案1】:

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

_ptr.push_back(&amp;(_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!

在使用push_back 之前,您可以使用reserve 来改善这一点。

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

但我不建议这样做。

【讨论】:

  • 即使我给 _ptr.push_back(&(_somevec[_somevec.size()-1])) 我也会得到同样的错误。添加新元素时,_somevec 中已存储元素的地址会改变吗?
  • 是的,如果向量需要重新分配它的内存。
  • 好的。因此,如果向量扩展,那么它可能会将其旧内容转移到一个全新的位置。这解释了当时的失败。谢谢
  • @SumanVajjala 如果这回答了您的问题,那么请接受答案。在 StackOverflow,我们不会说谢谢。我们接受并投票赞成答案。
【解决方案2】:

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

验证这个假设的最简单方法是查看对象向量的capacity() 是否发生变化。最简单的解决方法可能是使用std::deque&lt;mystruct&gt;,因为std::deque&lt;T&gt; 在任一端添加/删除对象时不会重新定位其对象。

【讨论】:

  • Kuhl 感谢您的意见。向量是否以连续的方式将对象存储在内存中?是因为std::deque在这里工作的存储分散吗?
  • 是的,std::vector&lt;T&gt; 使用连续的值序列,而std::deque&lt;T&gt; 使用大小相等的数组,也就是说,当空间不足时,它不需要移动现有对象。
猜你喜欢
  • 1970-01-01
  • 2013-03-31
  • 1970-01-01
  • 2012-07-12
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
  • 2017-02-12
相关资源
最近更新 更多