Reputation: 612
I think it is a trivial question, but I couldn't find a specific solution to it. I'm trying to append array into a vector, using push_back()
function. Here is the code:
int main()
{
std::vector<int*> matchVector;
int msmTemp[3];
msmTemp[0] = 1;
msmTemp[1] = 2;
msmTemp[2] = 3;
matchVector.push_back(msmTemp);
msmTemp[0] = 4;
msmTemp[1] = 7;
msmTemp[2] = 0;
matchVector.push_back(msmTemp);
for(auto i : matchVector)
{
for(int j = 0; j<3; j++)
{
cout<<i[j]<<", ";
}
cout<<"\n";
}
return 0;
}
The output I'm getting is 4,7,0 two times. I don't understand as to why I'm not able to see the previous values, namely 1,2,3? Is it because of the type of vector matchVector
defined above? I think it needs to be array only.
Upvotes: 5
Views: 16640
Reputation: 8598
The other answers already explain how to fix your code. I think it's also good to explain why your code behaves the way it does:
Here you tell your compiler to create an std::vector
that holds pointers to int:
std::vector<int*> matchVector;
Here you tell your compiler to allocate some space on the stack that fits 3 ints:
int msmTemp[3];
Here you tell your compiler to write the values 1
, 2
and 3
into the memory previously allocated:
msmTemp[0] = 1;
msmTemp[1] = 2;
msmTemp[2] = 3;
Here you tell your compiler to take the address of that allocated space, treat it as a pointer and pass it to push_back
. This is called array decaying:
matchVector.push_back(msmTemp);
Your matchVector
now contains 1 element, which is a pointer to the address of the memory on your stack that was allocated to hold 3 ints.
Here you tell your compiler to write the values 4
, 7
and 0
in the memory previously allocated. Note that this is still the same memory block as before:
msmTemp[0] = 4;
msmTemp[1] = 7;
msmTemp[2] = 0;
Here you tell your compiler to again take the address of the allocated space, treat it as a pointer and pass it to push_back
:
matchVector.push_back(msmTemp);
Thus matchVector
now contains 2 identical values, each a pointer to the same memory location. Specifically the memory location that you last wrote 4
, 7
and 0
into.
Upvotes: 2
Reputation: 275270
A int*
is a pointer to an integer.
An int[3]
is an array of 3 integers.
An array of 3 integers "decays" at the drop of a hat to a pointer to the first element.
When you do push_back(msmTemp)
, you push a pointer to the first element of msmTemp
into the vector
.
Pointers in C++ do not own what they point to. The vector afte the two push_backs contains two pointers, both to the same array msmTemp
.
When you later iterate over the vector, you get two pointers in turn. Each points to msmTemp
.
You then use []
to index those pointers. When you have a pointer to the first element of an array, you can use []
to access the other elements of the array. [0]
is the first element, [1]
the second, etc.
So you look at the 3 elements in msmTemp
(luckily it has 3) and look at them twice, because you have two pointers into it in the vector.
You can inject elements like this:
std::vector<int> matchVector;
int msmTemp[3];
msmTemp[0]={1};
msmTemp[1]={2};
msmTemp[2]={3};
matchVector.insert( matchVector.end(), std::begin(msmTemp), std::end(msmTemp) );
etc. This ends up with a vector containing 6 elements, not two arrays.
If you want arrays as values you need std::array
:
std::vector< std::array<int,3> > matchVector;
std::array<int, 3> msmTemp;
and then your code works as written. std::array
is a library type that acts sort of like a raw array, but it doesn't have the decay-to-pointer problems of a raw array.
Upvotes: 10
Reputation: 62576
Forget that int[3]
names a type. C arrays don't behave like sensible values. Arrays are named std::array<type, count>
.
#include <vector>
#include <array>
int main()
{
std::vector<std::array<int, 3>> matchVector;
std::array<int, 3> msmTemp;
msmTemp[0] = 1;
msmTemp[1] = 2;
msmTemp[2] = 3;
matchVector.push_back(msmTemp);
msmTemp[0] = 4;
msmTemp[1] = 7;
msmTemp[2] = 0;
matchVector.push_back(msmTemp);
for(auto & arr : matchVector)
{
for(auto i : arr)
{
std::cout << i <<", ";
}
std::cout<<"\n";
}
return 0;
}
Upvotes: 2