填充向量的指针向量产生奇怪的结果

时间:2016-04-18 14:33:22

标签: c++ pointers vector

简介

我有一个代码,我用integer值填充向量,并将其推送到指向向量的指针向量,如下所示:

std::vector<std::vector<int>*> set_of_vectors;

 for(int i = 0; i < 10; i++)
 { 
     //initialize vector
     std::vector<int> pos_vector;
     //fill it with 0s
     pos_vector.resize(10, 0);
     //fill it with integers
     fill_vector(pos_vector);
     //push into set_of_vectors
     set_of_vectors.push_back(&pos_vector);
  }

问题是输出真的很奇怪。输出应该等于

0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9

但相反,我得到以下输出:

9617952, 0, 2, 3, 4, 5, 6, 7, 8, 9,

完整源代码

 #include <vector>
#include <iostream>

void fill_vector(std::vector<int> & values);

int main()
{
   std::vector<std::vector<int>*> set_of_vectors;

   for(int i = 0; i < 5; i++)
   {
     std::vector<int> pos_vector;
     pos_vector.resize(10, 0);
     fill_vector(pos_vector);
     set_of_vectors.push_back(&pos_vector);
   }
  for(auto & vec:set_of_vectors)
  {
    for(auto &v:*vec)
    {
      std::cout << v <<", ";
    }
    std::cout << std::endl;
  }

  return 0;
}

void fill_vector(std::vector<int> & values)
{
  for(int i = 0; i < values.size(); i++)
  {
    values[i] = i;
  }
}

4 个答案:

答案 0 :(得分:4)

这是UB。

pos_vector是一个局部变量,当离开for循环时将被销毁,然后推入向量的指针(即&pos_vector)将是一个悬空指针,任何顺序在它上面是UB。

如果必须使用std::vector<std::vector<int>*>,则需要new指针:

for(int i = 0; i < 5; i++)
{
  std::vector<int>* pos_vector = new std::vector<int>;
  pos_vector->resize(10, 0);
  fill_vector(*pos_vector);
  set_of_vectors.push_back(pos_vector);
}

最后不要忘记delete

答案 1 :(得分:3)

您正在添加指向本地对象的指针。这些本地对象将在每个for循环结束时被销毁,并且你保持一个带有指针指向垃圾的向量(&#34;悬空指针&#34;)。

您可以定义std::vector<std::vector<int>> set_of_vectors并使用&set_of_vectors[idx]获取每个元素的指针。

以下代码从向量列表中创建指针列表,并可在库调用中使用:

std::vector<std::vector<int>*> set_of_ptrs;
set_of_ptrs.reserve(set_of_vectors.size()); 
for(auto& v: set_of_vectors)
   set_of_ptrs.push_back(&v);

答案 2 :(得分:1)

您必须执行类似

的操作
for(int i = 0; i < 5; i++)
{
  std::vector<int>* pos_vector = new std::vector<int>();
  pos_vector->resize(10, 0);
  fill_vector(*pos_vector);
  set_of_vectors.push_back(pos_vector);
}

您的示例会为您分配堆栈中分配的pos_vector地址的悬空指针。

答案 3 :(得分:0)

您必须将向量复制到数组中,pos_vector是一个局部变量,存储其引用将导致未定义的行为,因为向量一旦超出范围就会被删除。您还应将set_of_vectors定义为类型std::vector的{​​{1}}而不是std::vector<int>,因为您不希望存储超出范围的指针。

std::vector<int>*

借助#include <vector> #include <iostream> void fill_vector(std::vector<int>& values) { for(int i=0; i<values.size(); ++i) values[i] = i; } int main() { std::vector<std::vector<int>> set_of_vectors; for(int i = 0; i<5; ++i) { std::vector<int> pos_vector; pos_vector.resize(10, 0); fill_vector(pos_vector); set_of_vectors.push_back(pos_vector); } for(auto& vec : set_of_vectors) { for(auto& v : vec) { std::cout << v <<", "; } std::cout << std::endl; } return 0; } 功能,您可以大大简化作业。

std::iota