Reputation: 2441
I have a code where I fill a vector with integer
values and and push it into a vector of pointer to vectors as follows:
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);
}
The problem is the output is really weird. The output should shou be equal to
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
but on the contrary I am getting the following output:
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;
}
}
Upvotes: 1
Views: 313
Reputation: 1811
Your are adding pointers to local objects. These local objects will be destroyed at the end of each for-loop and you keep a vector with pointers pointing to garbage ("dangling pointers").
You could define a std::vector<std::vector<int>> set_of_vectors
and use &set_of_vectors[idx]
to get a pointer for each element.
The following code creates a list of pointers from a list of vectors and can be used in your library call:
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);
Upvotes: 3
Reputation: 6194
You have to copy the vector into the array, pos_vector
is a local variable and storing its reference will lead to undefined behavior as the vector is deleted once it goes out of scope. You should also define set_of_vectors
as a std::vector
of type std::vector<int>
and not of std::vector<int>*
as you do not want to store pointers there that will go out of scope.
#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;
}
You can simplify your assignment considerably with the help of the std::iota
function.
std::vector<std::vector<int>> set_of_vectors(5, std::vector<int>(10));
for(auto& vec : set_of_vectors)
std::iota(vec.begin(), vec.end(), 1);
Upvotes: 0
Reputation: 172964
This is UB.
pos_vector
is a local variable and will be destroyed when get out of the for
loop, then the pointer pushed into vector (i.e. &pos_vector
) will be a dangled pointer, any deference on it is UB.
If you have to use std::vector<std::vector<int>*>
, you need to new
a pointer:
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);
}
Don't forget to delete
them at last.
Upvotes: 4
Reputation: 1
You have to do something like
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);
}
Your example leaves you with dangling pointers for pos_vector
addresses allocated on the stack.
Upvotes: 1