程序的范围是创建一个Container对象,该对象存储在矢量Class对象中。然后,我要从向量的精确Class对象开始打印所有其前身。
class Class{
public:
Class(){
for (int i = 0; i < 10; ++i) {
Class c;
c.setName(i);
if (i > 0) {
c.setNext(_vec,i-1);
}
_vec.push_back(c);
}
}
};
~Class();
void setName(const int& n);
void setNext( vector<Class>& vec, const int& pos);
Class* getNext();
string getName();
void printAllNext(){ //print all next Class objects including himself
cout << _name <<endl;
if (_next != nullptr) {
(*_next).printAllNext();
}
}
private:
Class* _next;
string _name;
};
class Container{
public:
Container(){
for (int i = 0; i < 10; ++i) {
Class c;
c.setName(i);
if (i > 0) {
c.setNext(_vec,i-1);
}
_vec.push_back(c);
};
~Container();
void printFromVec(const int& n){//print all objects of _vec starting from n;
_vec[n].printAllNext();
};
private:
vector<Class> _vec;
};
int main() {
Container c;
c.printFromVec(5);
}
问题是所有Class对象的_next指针都是未定义或随机的。 我认为问题出在这部分代码上:
class Container{
public:
Container(){
for (int i = 0; i < 10; ++i) {
Class c;
c.setName(i);
if (i > 0) {
c.setNext(_vec,i-1);
}
_vec.push_back(c);
};
调试我注意到已经创建的对象的指针更改了它们的值。 出什么问题了?我该如何运作?
答案 0 :(得分:1)
尽管代码中确实存在错误(可能是错误的复制粘贴),但问题确实出在以下地方:std :: vector维护内部动态分配的对象数组。它以一定的初始大小开始。当按下向量时,它将填充数组的条目。当所有条目都已填充但您尝试推送更多元素时,vector分配更大的内存块并将对象移动或复制(无论您元素数据类型支持的对象)到新的内存位置。这就是对象地址更改的原因。
现在要说些什么。
解决方案1.使用std :: list代替std :: vector。 std :: list是双向链接列表,元素一旦添加到列表中,将成为列表项的一部分,并且不会更改其地址,没有重新分配。
解决方案2.使用共享指针的向量。在这种情况下,您将需要动态分配每个对象并将地址放入共享指针对象中,您可以使用函数std :: make_shared()一次完成这两个操作。然后将共享指针推到vector,并将std :: weak_pointer存储为指向上一个/下一个的指针。
解决方案3。如果您知道向量中可能存在的最大元素数,则可以保留所有元素,但在第一次执行操作之前要做另外一件事-在向量中调用reserve(),元素的最大数目为参数。 Vector将分配该大小的数组,并保留它,直到它被填充并需要更多空间为止。但是,由于分配了您期望的最大可能大小,因此永远不会发生重新分配,因此对象的地址将保持不变。
选择您认为最适合自己需求的解决方案。
答案 1 :(得分:1)
@ ivan.ukr 提供了许多用于保持指针稳定的解决方案。但是,我认为这是要解决的问题。
Class
对象可以指向容器中的上一个对象。这是实际问题:从容器中的某个点向后迭代。 _next
指针是对实际问题(迭代)的不完整解决方案。
如果要迭代向量,请使用迭代器。您可以在cppreference page for std::vector上阅读有关它们的信息。我不想为您编写代码,但会给您一些提示。
i
个元素的迭代器,请使用auto iter = _vec.begin() + i;
。iter->print()
(您必须将printAllNext
重命名为print
,并仅打印此对象)。--iter
。iter == _vec.begin()
。您可以通过使用反向迭代器来进一步改善这一点,但我将由您自己决定。