I am kind of a beginner and just came across the concept of vectors in C++. I have a few questions about it
1. Is there a concept of 2-D vectors in C++? if yes, then how do i declare corresponding to a 2-D Matrix a[n][m]? Here, n and m are variables.
2. How are vectors passed as arguments to functions? By default are they passed by reference or by value?
3. Are there any performance benifits of vectors over arrays in C++?
1 - There's no real concept of dimensions per se. But you can create "nested" types. For example:
std::vector <int> intVec;
std::vector < std::vector <int> > doubleIntVec;
Here, intVec can be compared to single-dimension vector, doubleIntVec to double dimension, and so on. The types don't have to be the same, you can do std::vector < std::vector <char> > doubleIntVec for example, which is why "dimension" is not the right term here.
2 - Like any other type, there's no specific treatment of vectors.
3 - Yes, for example if you need resizing them, but you can implement arrays to behave similarly. Other than that the benefit is the standardization, the memory management that comes built in, the additional methods, and the various STL algorithms that can be run on vectors (being it a standard container).
There's no 2-D vectors in C++, to create a matrix, you can use vectors of vectors.
using namespace std;
int m, n;
// ...
vector<vector<int> > v(n);
for (int y = 0; y < n; y++)
v[n].resize(m);
// ...
Computing libraries won't implement them this way, though.
To pass a vector by reference to a function, use:
void function(vector & v);
Omitting the & will result in the vector being copied during the function call.
Vectors have the same performance as C arrays, but are much more practical to use.
No need to manually manage the memory, and the vector size is always accessible.
You also have automatic copy and guarantees on contiguity of values (raw data can be accessed by vector::data()
vector in C++ is just a sequence container. So, it's possible using it to hold a 2D array.
Using std::vector <std::vector<int>>
It depends on the purpose.
Not perfomance wise, but unlike array, std::vector is growable.
Related
I am trying to initialize an array of a vector of ints.
This is my code:
vector<int> *vec[] = new vector<int>[n+1];
I get the following compilation error:
initialization with '{...}' expected for aggregate object
What's wrong with this ?
If you need an array (in the broad sense) of elements of type vector<int>, I advise you to use:
std::vector<std::vector<int>> vec(n+1);
vec will be a vector of vectors. The number of vectors will be n+1 like it seems you wanted. std::vector will manage the memory for you, so there's no need for new/delete.
In C++ we also have std::array, but it looks like the number of elements in vec is dynamically dependant on n, which makes a topmost std::vector the proper fit.
There are many advantages using C++ std::vector/std::array over C style arrays. See e.g. the answers here: std::vector versus std::array in C++.
If you must use a C style topmost array, see the other answer.
The problem is that you're trying to initialize an array of pointers to vector with a "pointer to a vector".
To solve this you can either remove the [] from the left hand side of the declaration or not mix std::vector and raw pointers.
//--------------v----------------------->removed [] from here
vector<int> *vec = new vector<int>[n+1];
I just started learning graphs data structure and came through the adjacency matrix and adjacency lists.
The Adjacency list use vector<int> vec[n], where n is the number of vertices.
But I think that the working of vector<int> vec[n] i.e so-called adjacency list is same as the vector of vectors...i.e vector<vector<int>> vec.
Please help me out with this!
Let's start simple:
int arr[n];
std::vector<int> vec;
arr is a C array of ints. This data type is very bare bone. You can't easily get its size and lacks all of the modern OOP features. It has a lot of other problems e.g.:
in most contexts it decays to pointer
the return type cannot be array
you can't have array type as function parameter - what looks like a C array type is in fact a pointer type
vec is a proper C++ container representing a dynamic vector. You can access its size, you can grow it, shrink it etc.
Don't use C arrays. Use standard containers. std::vector should be the first choice. If the size is known at compile time and it doesn't change use std::array instead.
vector<int> vec[n]
Is a freakish Frankenstein's monster. It's a C array of vectors of ints.
is same as the vector of vectors...i.e vector<vector<int>> vec
Close. The C++ equivalent would be std::array<std::vector<int>, n>.
Note: there are some compilers (most notably gcc and clang) that accept n as a non constant size for a C array (the so called Variable Length Arrays), but that isn't standard and portable.
Both are not equivalent
std::vector<int> vec[n];
declares an fixed size array of size n where n must be known at compile time (or a compiler extension must be available). During the initialization of vec the constructors of all n vectors are called. These vectors are allocated on the stack.
std::vector<std::vector<int>> vec;
creates an empty vector of vectors though. The constructor of std::vector<int> is never called. You need to call
vec.resize(n);
to change the size of vec to n calling the constructors of std::vector<int> n times. In contrast to std::vector<int> vec[n]; n does not need to be a compile time constant with this approach. Furthermore you can apply other operations on a std::vector<std::vector<int>> changing the number of elements further.
In the second version the std::vector<int> objects are allocated on the heap. (The elements of the std::vector<int>s are stored different locations on the heap.)
In this declaration
std::vector<int> vec[n];
there is declared an array. You can not resize the array for example removing or adding new elements.
On the other hand, using this declaration
std::vector<std::vector<int>> vec( n );
you can resize the vector removing or adding new elements.
Another problem is that arrays do not have the assignment operator.
Also arrays do not have comparison operators.
vector<int> vec[n];
is an array (a so called C-Style array) of size n with elements of type vector<int>
vec can't grow / shrink in size, however it's elements can (.resize(), .push_back(), .pop_back())
vector<vector<int>> vec;
is a two dimensional vector of type int
vec can grow / shrink to any size, and it's element can do so as well.
which one is better? For your case the vector<vector<int>> probably, but it really depends on the use, C-Style arrays require you know the size before, but can be more optimized as the memory will be on the stack. For example, if you know the size of the matrix beforehand, you can use a pure 2d C-Style array:
int matrix[n][m];
With C-Style arrays you loose the size when passed to a function, so std::array is preferred here, they are as optimized and come with utilities such as .size(), .back() etc:
std::array<std::array<int, m>, n> matrix;
My question is simple: are std::vector elements guaranteed to be contiguous? In other words, can I use the pointer to the first element of a std::vector as a C-array?
If my memory serves me well, the C++ standard did not make such guarantee. However, the std::vector requirements were such that it was virtually impossible to meet them if the elements were not contiguous.
Can somebody clarify this?
Example:
std::vector<int> values;
// ... fill up values
if( !values.empty() )
{
int *array = &values[0];
for( int i = 0; i < values.size(); ++i )
{
int v = array[i];
// do something with 'v'
}
}
This was missed from C++98 standard proper but later added as part of a TR. The forthcoming C++0x standard will of course contain this as a requirement.
From n2798 (draft of C++0x):
23.2.6 Class template vector [vector]
1 A vector is a sequence container that supports random access iterators. In addition, it supports (amortized)
constant time insert and erase operations at the end; insert and erase in the middle take linear time. Storage
management is handled automatically, though hints can be given to improve efficiency. The elements of a
vector are stored contiguously, meaning that if v is a vector where T is some type other
than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().
As other answers have pointed out, the contents of a vector is guaranteed to be continuous (excepting bool's weirdness).
The comment that I wanted to add, is that if you do an insertion or a deletion on the vector, which could cause the vector to reallocate it's memory, then you will cause all of your saved pointers and iterators to be invalidated.
The standard does in fact guarantee that a vector is continuous in memory and that &a[0] can be passed to a C function that expects an array.
The exception to this rule is vector<bool> which only uses one bit per bool thus although it does have continuous memory it can't be used as a bool* (this is widely considered to be a false optimization and a mistake).
BTW, why don't you use iterators? That's what they're for.
As other's have already said, vector internally uses a contiguous array of objects. Pointers into that array should be treated as invalid whenever any non-const member function is called IIRC.
However, there is an exception!!
vector<bool> has a specialised implementation designed to save space, so that each bool only uses one bit. The underlying array is not a contiguous array of bool and array arithmetic on vector<bool> doesn't work like vector<T> would.
(I suppose it's also possible that this may be true of any specialisation of vector, since we can always implement a new one. However, std::vector<bool> is the only, err, standard specialisation upon which simple pointer arithmetic won't work.)
I found this thread because I have a use case where vectors using contiguous memory is an advantage.
I am learning how to use vertex buffer objects in OpenGL. I created a wrapper class to contain the buffer logic, so all I need to do is pass an array of floats and a few config values to create the buffer.
I want to be able to generate a buffer from a function based on user input, so the length is not known at compile time. Doing something like this would be the easiest solution:
void generate(std::vector<float> v)
{
float f = generate_next_float();
v.push_back(f);
}
Now I can pass the vector's floats as an array to OpenGL's buffer-related functions. This also removes the need for sizeof to determine the length of the array.
This is far better than allocating a huge array to store the floats and hoping I made it big enough, or making my own dynamic array with contiguous storage.
cplusplus.com:
Vector containers are implemented as dynamic arrays; Just as regular arrays, vector containers have their elements stored in contiguous storage locations, which means that their elements can be accessed not only using iterators but also using offsets on regular pointers to elements.
Yes, the elements of a std::vector are guaranteed to be contiguous.
I'm new to C++ STL, and I'm having trouble comprehending the graph representation.
vector<int> adj[N];
So does this create an array of type vector or does this create a vector of arrays? The BFS code seems to traverse through a list of values present at each instance of adj[i], and hence it seems works like an array of vectors.
Syntax for creating a vector is:
vector<int> F;
which would effectively create a single dimensional vector F.
What is the difference between
vector< vector<int> > N;
and
vector<int> F[N]
So does this (vector<int> adj[N];) create an array of type vector or does this create a
vector of arrays?
It creates array of vectors
What is the difference between
vector< vector<int> > N;
and
vector<int> F[N]
In the first case you are creating a dynamic array of dynamic arrays (vector of vectors). The size of each vector could be changed at the run-time and all objects will be allocated on the heap.
In the second case you are creating a fixed-size array of vectors. You have to define N at compile-time, and all vectors will be placed on the stack†, however, each vector will allocate elements on the heap.
I'd always prefer vector of vectors case (or the matrix, if you could use third-party libraries), or std::array of std::arrays in case of compile-time sizes.
I'm new to C++ STL, and I'm having trouble comprehending the graph
representation.
You may also represent graph as a std::unordered_map<vertex_type,std::unordered_set<vertex_type>>, where vertex_type is the type of vertex (int in your case). This approach could be used in order to reduce memory usage when the number of edges isn't huge.
†: To be precise - not always on stack - it may be a part of a complex object on the heap. Moreover, C++ standard does not define any requirements for stack or heap, it provides only requirements for storage duration, such as automatic, static, thread or dynamic.
Short Answer:
It's an array of vector <int>s.
Long Answer:
When reading a declaration such as
vector<int> adj[N];
The compiler uses a method known as the "spiral-" or "clockwise-rule" in order to interpret what it means. The idea behind the spiral rule is that you start at the variable name, and move outwards in a clockwise spiral in order to figure out what type of variable it is. For example:
char* str [10];
Can be interpreted like this:
____
| |
char* str [10];
|_________|
Making str an array of 10 char*s.
Therefore, vector<int> adj[N]; is an array of vectors rather than a vector of arrays
Practice makes perfect:
1: What does int * foo [ ]; mean?
Answer:
"foo" is an array of pointers to integers
2: What does int * (*foo [ ] )(); mean?
Answer:
"foo" is an array of pointers to functions returning pointers to integers
3: What does int * (*(*foo [ ] )())(); mean?
Answer:
"foo" is an array of pointers to functions returning pointers to functions returning pointers to integers
vector<int> arr[N];
It displays an array of vector, each array[i] would have a vector stored in it that can traverse through many values. It is like a an Array of Linked List where the heads are only stored in array[i] positions.
vector<vector<int> > N vs vector<int> F[N]
The difference between 2D Vector and an Array of Vector is that 2D Vectors can span in size while array of vectors have their dimension fixed for the array size.
Under the hood a vector still uses array, it is implementation specific but is safe to think that:
vector<int>
internally creates an int[].
What vectors gives you is that it abstract from you the part where if you want to re-size you don't have to re-allocate manually etc, it does that for you (plus much more of course).
When you do: vector<vector<int>> you are going to create a vector of vectors, meaning a 2D matrix. You can nest it as much as you want.
Vector takes in a type T and allocates an array of that type. so if you pass vector as type T, it will effectively do what you did in your first line, an array of vector<int>.
Hope it makes sense
My question is simple: are std::vector elements guaranteed to be contiguous? In other words, can I use the pointer to the first element of a std::vector as a C-array?
If my memory serves me well, the C++ standard did not make such guarantee. However, the std::vector requirements were such that it was virtually impossible to meet them if the elements were not contiguous.
Can somebody clarify this?
Example:
std::vector<int> values;
// ... fill up values
if( !values.empty() )
{
int *array = &values[0];
for( int i = 0; i < values.size(); ++i )
{
int v = array[i];
// do something with 'v'
}
}
This was missed from C++98 standard proper but later added as part of a TR. The forthcoming C++0x standard will of course contain this as a requirement.
From n2798 (draft of C++0x):
23.2.6 Class template vector [vector]
1 A vector is a sequence container that supports random access iterators. In addition, it supports (amortized)
constant time insert and erase operations at the end; insert and erase in the middle take linear time. Storage
management is handled automatically, though hints can be given to improve efficiency. The elements of a
vector are stored contiguously, meaning that if v is a vector where T is some type other
than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().
As other answers have pointed out, the contents of a vector is guaranteed to be continuous (excepting bool's weirdness).
The comment that I wanted to add, is that if you do an insertion or a deletion on the vector, which could cause the vector to reallocate it's memory, then you will cause all of your saved pointers and iterators to be invalidated.
The standard does in fact guarantee that a vector is continuous in memory and that &a[0] can be passed to a C function that expects an array.
The exception to this rule is vector<bool> which only uses one bit per bool thus although it does have continuous memory it can't be used as a bool* (this is widely considered to be a false optimization and a mistake).
BTW, why don't you use iterators? That's what they're for.
As other's have already said, vector internally uses a contiguous array of objects. Pointers into that array should be treated as invalid whenever any non-const member function is called IIRC.
However, there is an exception!!
vector<bool> has a specialised implementation designed to save space, so that each bool only uses one bit. The underlying array is not a contiguous array of bool and array arithmetic on vector<bool> doesn't work like vector<T> would.
(I suppose it's also possible that this may be true of any specialisation of vector, since we can always implement a new one. However, std::vector<bool> is the only, err, standard specialisation upon which simple pointer arithmetic won't work.)
I found this thread because I have a use case where vectors using contiguous memory is an advantage.
I am learning how to use vertex buffer objects in OpenGL. I created a wrapper class to contain the buffer logic, so all I need to do is pass an array of floats and a few config values to create the buffer.
I want to be able to generate a buffer from a function based on user input, so the length is not known at compile time. Doing something like this would be the easiest solution:
void generate(std::vector<float> v)
{
float f = generate_next_float();
v.push_back(f);
}
Now I can pass the vector's floats as an array to OpenGL's buffer-related functions. This also removes the need for sizeof to determine the length of the array.
This is far better than allocating a huge array to store the floats and hoping I made it big enough, or making my own dynamic array with contiguous storage.
cplusplus.com:
Vector containers are implemented as dynamic arrays; Just as regular arrays, vector containers have their elements stored in contiguous storage locations, which means that their elements can be accessed not only using iterators but also using offsets on regular pointers to elements.
Yes, the elements of a std::vector are guaranteed to be contiguous.