如何在C ++中正确推回向量中的一系列对象?

时间:2019-07-06 22:22:49

标签: c++

程序的范围是创建一个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);
    };

调试我注意到已经创建的对象的指针更改了它们的值。 出什么问题了?我该如何运作?

2 个答案:

答案 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()

您可以通过使用反向迭代器来进一步改善这一点,但我将由您自己决定。