我有一个小代码片段,会在运行时产生错误。以下代码存储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]));
}
我不知道我在做什么错。非常感谢您的帮助/投入!!
答案 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>
在两端添加/删除对象时不会重定位其对象。