为什么附加向量会丢弃数据

Why are appended vectors throwing away data?

本文关键字:数据 向量 为什么      更新时间:2023-10-16

我在一个带指针的大向量中包含了许多向量。现在我想根据任意条件合并这个列表中的向量。这包括首先将两个向量附加在一起,然后从"大"向量中删除其中一个。

当我运行这个程序时,我偶尔会遇到这样的情况,长度为6和12的向量合并在一起,总长度为12(因此丢弃了6个元素)。

我试图在一个包含的C++文件中重新创建这个问题。我没有完全处理好(这个抛出了一个不可调试的索引越界错误)。据我所知,我在这里搞砸了很多事情。

#include <stdio.h>
#include <math.h>
#include <iostream>
#include <fstream>
int main(int argc, char** argv)
{
    std::vector<std::vector<int>*> lists;
    //create lists with variable size
    for(int i = 0; i < 100; i++) {
        std::vector<int> vec;
        for(int j = 0; j < i; j++) {
            vec.push_back(j);
        }
        lists.push_back(&vec);
    }
    //do the merging
    bool changed = true;
    while(changed) {
        changed = false;
        for(int list = 0; list < (int)lists.size(); list++) {
            std::vector<int>* listInstance = lists.at(list);
            for(int otherList = 0; otherList < (int)lists.size(); otherList++) {
                if(list == otherList) {//avoid merging lists with themselves
                    continue;
                }
                std::vector<int>* otherListInstance = lists.at(otherList);
                if(lists.at(otherList)->size() % 4 == 0) { //some arbitrary condition for merging.
                    changed = true;
                    int otherSize = otherListInstance->size();
                    listInstance->insert(listInstance->end(), otherListInstance->begin(), otherListInstance->end());
                    lists.erase(lists.begin() + otherList);
                    if(otherSize != otherListInstance->size()) {
                        std::cout << "Does not match!n";
                    }
                    otherList--;
                }
            }
        }
    }
    return 0;
}

您正在将指针推送到局部变量。这是未定义的行为。

更改

std::vector<std::vector<int>*> lists;
//create lists with variable size
for(int i = 0; i < 100; i++) {
    std::vector<int> vec;
    for(int j = 0; j < i; j++) {
        vec.push_back(j);
    }
    lists.push_back(&vec);
}

std::vector<std::vector<int>> lists;
//create lists with variable size
for(int i = 0; i < 100; i++) {
    std::vector<int> vec;
    for(int j = 0; j < i; j++) {
        vec.push_back(j);
    }
    lists.push_back(vec);
}

或者使用new创建一个非本地版本。

std::vector<std::vector<int> *> lists;
//create lists with variable size
for(int i = 0; i < 100; i++) {
    std::vector<int> * vec = new std::vector<int>();
    for(int j = 0; j < i; j++) {
        vec->push_back(j);
    }
    lists.push_back(vec);
}

当然,最好使用std::vector<std::shared_ptr<std::vector<int> > >作为列表的类型。这样,您就不需要进行手动内存管理。

如果局部变量超出范围,则将指针推送到局部变量会产生未定义的行为:

for (int i = 0; i < 100; i++) {
    std::vector<int> vec;
    for (int j = 0; j < i; j++) {
        vec.push_back(j);
    }
    lists.push_back(&vec); // Pointer to an in-scope local variable
}
// Now lists contains pointers to invalid stack areas

由于你似乎只是想创建一个int向量的向量,你可以简单地存储它而不需要指针:

std::vector<std::vector<int>> lists;
for (int i = 0; i < 100; i++) {
    std::vector<int> vec;
    for (int j = 0; j < i; j++) {
        vec.push_back(j);
    }
    lists.push_back(vec);
}

随着这种变化(显然也改变了对成员访问的每次取消引用),例如

lists.at(otherList)->size() ---> lists.at(otherList).size()

你的代码会做得很好。

如果你真的需要/想要使用指针,请确保在堆上分配它们,我还建议使用智能指针来存储它。