Memory allocation in C++ STL for dynamic containers - c++

When you declare 2D arrays, they are stored in contiguous memory locations and this is easy as the number of rows is fixed while declaring them.
Whereas when we declare a 2D vector vector<vector<int>> v, how does it work. As the number of rows is not fixed at all. My first guess was the new vector which you push_back into it are randomly allocated but then even that wont work as these vectors of int are randomly accessible.
My first guess is to allocate vectors of int randomly in the memory and store their address in another vector of addresses.
eg
vector<vector<int>> vmain;
vector<int> a = {1, 2, 3};
vector<int> b = {1, 2, 3};
vector<int> c = {1, 2, 3};
vmain.push_back(a);
vmain.push_back(b);
vmain.push_back(c);
is stored something similar to
vector<&vector<int>> vmain; //vector of pointer to vector
vector<int> a = {1, 2, 3};
vector<int> b = {1, 2, 3};
vector<int> c = {1, 2, 3};
vmain.push_back(&a);
vmain.push_back(&b);
vmain.push_back(&c);
Please tell me if this is the correct way.
And also for vector of maps or sets vector<map<int, int>> v1 and vector<set<int>> v2. As size of maps and sets is not fixed.

The vector object doesn't store the elements. It stores a pointer to a contiguous chunk of memory containing the elements. When you have std::vector<std::vector<int>> the outer vector contains a pointer to a contiguous chunk of memory containing vector objects, each of which have a pointer to a contiguous chunk of memory containing the ints.
std::map and std::set also don't store the elements in the object itself. Each object contains a pointer to a BST containing the elements.

Related

Create a vector in C++ with constant values

I want to create a vector by determining the size and the constant value which the vector has, e.g. a vector of the size 5 and only 3 as values.
vector = {3, 3, 3, 3, 3}
I only know how to create a vector with zero as value with std::vector<int> vec(5);
You can use a constructor that accepts a count and a value.
std::vector<int> v (5,3);
Will result in having a vector of a size 5 and 3 as a values {3,3,3,3,3}.

Resizing array, does this code influence it badly in any way?

I've seen bunch of tutorials and threads, but no-one does this to resize an array. My question is, whether this affects bad something in my program or is there better way to resize it?
//GOAL:Array to become {1,2,4,5,6,7,8,9}
int size=9;
int array[size] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i = 2; i < 8; ++i)
array[i] = array[i + 1];
//ARRAY IS NOW{1, 2, 4, 5, 6, 7, 8, 9, 9}
//GOAL: TO DELETE THAT LAST 9 FROM ARRAY
size=8;
array[size];
//IT SHOULD BE {1,2,4,5,6,7,8,9} now, but does it effect my program in any negative context?
int array[size] declares an array of size elements.
Outside of a declaration, array[size] access element size in array. It does not resize the array. If you do something like that without changing the value of size, it actually tries to access the element after the last element in the array; not a good idea. In this case, since you changed size to be one less than the original, it accesses the last element of the array, which is safe but does not do what you want.
You can not resize an array in C/C++ that is declared on the stack (one allocated on the heap with malloc could be reallocated to a different size, but you'd have trouble copying it as the newly allocated array of the new size is possibly at a completely different memory location; you'd have to save the old one, allocate a new one of the new size, copy the elements you want, and then free the old one.)
If you want something resizeable, you are in C++; use a container (vector, for example, but pick the one that most suits your needs).
And....I just saw arnav-borborah's comment; don't know how I missed that. You can't even declare the array like that, as size is not a compile time constant.
Until size variable is not constexpr, this
int size=9;
int array[size] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
is Variable length array, which is not part of c++ standard, only extension of some compilers.
Also automatic arrays are not resizeable, they have fixed size since declaration until they goes out of scope.
You should use some STL container, like std::array, std::vector.
std::array needs to know size at compile time, so there is the best approach, std::vector, which is easy to use and resizeable.
// #include<vector>
std::vector<int> array { 1,2,3,4,5,6,7,8,9 }; // Uniform initialization
// Remove last element
array.pop_back(); // 'array' has now only 8 elements (1..8)
EDIT
As mentioned in comments, if you want to remove n-th element in vector, you may do
array.erase(array.begin()+n);
and job is done.
Hugely. say if you have a payload of 1GB and you Array.Resize the destination array in chunks of 10k then most of your application CPU and wait states will be resizing that array.
If you pre-allocate the array to 1GB, populating that array will be orders of magnitude faster. This is because every time you use Array.Resize.
The computer needs to move that memory in its entirety to another location in memory just to add the extra length you resized it by.
But of cause if you are dealing with very small arrays. This effect is not noticeable.

Static Multi Dimensional Arrays ( C/C++)

Is memory allocated for multidimensional arrays in C or C++ always contiguous, or is the storage dependent on the compiler? If it is guaranteed to be contiguous is there a standard on it somewhere for reference? For example
int x[2][2] = { { 1 , 2 } , { 5 , 10 } } ;
Are the integers 1, 2, 5, 10 in sequence in memory ?
Arrays are guaranteed contiguous. What we have here is an array of arrays - each layer of which is contiguous. The inner most arrays we know must be {1, 2} and {5, 10}, and the outer most array must also be contiguous. Therefore, {{1,2},{5,10}} must be 1, 2, 5, 10 sequentially in memory.
Yes. Arrays are always allocated in contiguous memory location. It doesn't matter whether its a single or multi dimensional array.

Difference between vector <int> V[] and vector< vector<int> > V

vector <int> V[] and vector< vector<int> > V both are 2D arrays.
But what is the difference between them and where do we use each one? Please give a brief explanation.
vector<int> V[] is an array of vectors.
vector< vector<int> > V is a vector of vectors.
Using arrays are C-style coding, using vectors are C++-style coding.
Quoting cplusplus.com ,
Vectors are sequence containers representing arrays that can change in
size.
Just like arrays, vectors use contiguous storage locations for their
elements, which means that their elements can also be accessed using
offsets on regular pointers to its elements, and just as efficiently
as in arrays. But unlike arrays, their size can change dynamically,
with their storage being handled automatically by the container.
TL;DR:
When you want to work with a fixed number of std::vector elements, you can use vector <int> V[].
When you want to work with a dynamic array of std::vector, you can use vector< vector<int> > V.
One difference would be that although both can be initialized in the same way, e.g.
vector<int> V1[] {{1,2,3}, {4,5,6}};
vector<vector<int>> V2 {{1,2,3}, {4,5,6}};
and accessed
cout << V1[0].back() << endl;
cout << V2[0].back() << endl;
the V1 can't grow. You cannot make V1.push_back(...) as its not a vector object. Its just an array. Second one is dynamic. You can grow it as you please.
vector<vector<int>> v(26); is a vector containing vectors. In this example, you have a vector with 26 vectors contained in it. The code v[1].push_back(x) means that x is pushed back to the first vector within the vectors.
vector<int> a[26]; is an array of vectors. In other words, a one-dimensional array containing 26 vectors of integers. The code a[1].push_back(x); has x being pushed back to the first index of the array.
vector<int> v[] is an array of vectors. That is, it is an array which contains vectors as its elements.
So, you cannot change the size of the array part, but we can add to its elements which is vector.
For example,
1.vector<int> v1[] = {{1},{2},{3}}; // array that contains 3 vector elements.
2.vector<vector<int>> v2 = {{1},{2},{3}}; // vector that contains 3 vector elements.
So for the first we cannot change the size of v but we can add or delete elements to its elements since it is a vector.
v1.push_back(4); // this will give an error since we cannot the predefined size of array.
v1[1].push_back(4); // this is acceptable since we are changing the vector part.
This makes the v1 {{1},{2,4},{3}}
For the second one, we can change both the overall size and its elements.
v2.push_back(4); // this is acceptable since it is vector.
vector V[] is just a fixed array; and so you can add/modify only till the upper limit. It is not a vector per se, and so has a fixed size limit.
However vector< vector > V is a dynamic vector and its size can be increased dynamically.

C++ Initialize array pointer

How do I initialize a pointer to a literal array?
I want *grid to point to the new allocated int array {1, 2, 3}.
int *grid = new int[3];
*grid = {1, 2, 3};
thank you.
You can't initialize a dynamically allocated array that way. Neither you can assign to an array(dynamic or static) in that manner. That syntax is only valid when you initialize a static array, i.e.
int a[4] = {2, 5, 6, 4};
What I mean is that even the following is illegal:
int a[4];
a = {1, 2, 3, 4}; //Error
In your case you can do nothing but copy the velue of each element by hand
for (int i = 1; i<=size; ++i)
{
grid[i-1] = i;
}
You might avoid an explicit loop by using stl algorithms but the idea is the same
Some of this may have become legal in C++0x, I am not sure.
#above grid points to the address location where the first element of the array grid[] is stored. Since in C++ arrays are stored in contiguous memory location, you can walk through your array by just incrementing grid and dereferencing it.
But calling grid an (int*) isnt correct though.
I'm not sure if this is obvious but you can do this in one line.
int *grid = new int[3] {1, 2, 3};
Since this is C++ we are talking about you can also split it into
two files. Where your .h file contains:
int *grid;
And your .cpp file contains:
grid = new int[3] {1, 2, 3};
Use the following code, grid is a pointer, grid[] is an element of that pointer.
int grid[] = {1 , 2 , 3};