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

时间:2014-11-08 12:58:45

标签: c++

我有一些带有指针的大向量中包含的向量。现在我想基于任意条件合并此列表中的向量。这包括首先将两个向量附加在一起,然后从“大”向量中删除其中一个。

当我运行程序时,我偶尔会得到一个长度为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;
}

2 个答案:

答案 0 :(得分:2)

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

更改

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> > >作为列表类型。这样,您就不需要进行手动内存管理。

答案 1 :(得分:1)

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

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

你的代码会做得很好。

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