#include <iostream>
#include <vector>
int main()
{
static const unsigned TOTAL = 4;
std::vector<int> v[TOTAL];
v[2].push_back(37);
//std::cout << v.size(); error
std::cout << v[0].size();
std::cout << v[2].size();
return 0;
}
Is is valid to instatnitate std::vector with bracket like in the code above?
MSVS and ideone compile it just fine, but vector is messed up (see error line).
I know I can use resize, but what is going on here?
You are creating a TOTAL sized array of vectors.
What you need is
std::vector<int> v(TOTAL);
This constructs a vector with TOTAL zero-initialized ints.
Then,
std::cout << v.size() << std::endl; // prints 4
std::cout << v[0] << std::endl; // prints 0
and so on.
It is valid to instantiate std::vector with bracket like in the code, but with different meanings.
std::vector<int> v[TOTAL];
Here you defined a vector v of size=TOTAL, each element of which is a vector<int>. Initially, these TOTAL vector<int>s are all empty (i.e. size=0).
After you call v[2].push_back(37);, v[2] will become a vector<int> of size=1 with a value 37 in it.
So the output you for the following will be 0 and 1.
std::cout << v[0].size();
std::cout << v[2].size();
If you want to call size(), you should call v[i].size() or define it as vector<int> v(TOTAL); (v is a vector of size=TOTAL, each element of which is an int).
I know I can use resize, but what is going on here?
you are basicly creating an array of type std::vector<int>, just as in here:
int arr[TOTAL];
Is is valid to instatnitate std::vector with bracket like in the code above?
you can have an array of vectors, but from your post it is not what you are after.
If you want to give your vector some initial size then use
std::vector<int> v(TOTAL);
this will set initial size of your vector to TOTAL, and value initialize all elements (set them to zero).
But you might actually want to:
std::vector<int> v;
v.reserve(TOTAL); // this is not necessary
// v.size() is zero here, push_back will add elements starting from index 0
because in case of std::vector<int> v(TOTAL); your push_back will start adding from index TOTAL.
Related
While taking a look at a solution for a problem, I came across this implementation of a vector.
const int MX = 100000;
std::vector <int> adj[MX];
The push_back() function doesn't work with this implementation of the vector class, and to add an element, the following code was used:
std::ifstream fin ("file.in");
int N = 5;
for (int i = 0; i < (N-1); i++) {
int A,B; fin >> A >> B; // reading values from another file
adj[A].pb(B), adj[B].pb(A);
}
The way this code is adding is adding pushing back a value to a certain part of the list, which I imagine as a vector inside the vector of the form:
{
{ },
{ }
}
In addition, how would I loop through this vector because for (int n : adj) does not work. I am not sure what the form of this vector is because this method of looping does not work.
What you have is C style array of vectors, off the bat you could replace that with std::array:
std::array<std::vector<int>, MX> adj;
To loop through these you would have to use a nested one, the outer loop to go through the array, and the inner one to go through each vector, something like this:
const int MX = 3;
//array of 3 vectors
std::array<std::vector<int>, MX> adj {{{1,2,3,4}, {5,6,7,8}, {9, 10, 11, 12}}};
for(auto &v : adj){ //for the array
for(auto i : v){ //for each vector
std::cout << i << " ";
}
std::cout << "\n";
}
Output:
1 2 3 4
5 6 7 8
9 10 11 12
You can also access individual elements using C style indexing:
std::cout << adj[1][0]; // vector element index 0 of array index 1
Or in a safer way, using container member at:
std::cout << adj.at(1).at(0);
This would output 5.
You should be careful though, when randomly filling the array, an array is not meant to have empty elements, otherwise the loops will go through uninitialized array members, which is not ideal, perhaps you are looking for some other kind of container.
I would like to write to internal array of vector. I could write using data() if vector is initialised.
However if the vector is empty (but having enough storage), I am not able to write directly to internal array of vector.
#include <vector>
#include <iostream>
using namespace std;
void write_seq(int *v, size_t len)
{
for (int i = 0; i < len; i++)
v[i] = i;
}
int main(void)
{
vector<int> v;
cout << "reserve and write\n";
v.reserve(10);
write_seq(v.data(), v.capacity());
cout << "seq length " << v.size() << "\n";
return 0;
}
Output:
$ g++ main.cpp && ./a.out
reserve and write
seq length 0
How to avoid this kind of situations, is it possible to validate data() pointer of vector?
Edit:
I assumed two things with this question, on an empty vector v;,
v.reserve(10) allocates memory for 10 elements and
v.data() points to that allocated memory.
You want to use resize, not reserve, and size instead of capacity. reserve simply gives the vector the added capacity, without actually increasing the size. resize increases the size to match the reserved capacity.
There's no need to concern yourself with how much memory you need to reserve beforehand. If performance is not really an issue, you may consider instead using auto-resizable back inserting iterators to push the elements at the step you want to push them.
#include <vector>
#include <iostream>
template<typename Iterator>
void write_seq(Iterator v) {
for (int i = 0; i < 10; i++) {
*v = i; // actually calls std::vector<>::push_back() internally
v++;
}
}
int main(void)
{
std::vector<int> v;
std::cout << "just write them data!\n";
write_seq(std::back_inserter(v));
std::cout << "seq length " << v.size() << "\n";
return 0;
}
You need to understand the concept of size and capacity of a vector. size is the number of elements stored while capacity is internal space allocated. capacity is always great than or equal to size. If you insert elements into the vector and caused the vector to run out of capacity, it will automatically increase its capacity by allocating a new space twice of current capacity, then copy existing elements into the new space, then delete the old space.
If you are planning to insert a large number of elements into a vector, the "auto increasing capacity" feature is not efficient, as it will keep allocating new spaces and copying elements. Instead, you can use reserve() to allocate enough space beforehand, and thus to avoid the process to keep allocating new spaces.
capacity(): Returns the number of elements that the container has currently allocated space for.
reserve(): Increase the capacity of the vector to the given size or more.
size(): Returns the number of elements in the container.
resize(): Changes the number of elements stored.
Back to your question, you can simply replace reserve with resize:
int main(void)
{
vector<int> v;
cout << "reserve and write\n";
v.resize(10); // use resize() instead of reserve()
write_seq(v.data(), v.size());
cout << "seq length " << v.size() << "\n";
return 0;
}
Or, you can insert into the vector directly:
void write_seq(vector<int>& v, size_t len)
{
for (int i = 0; i < len; i++)
v.push_back(i); // add an element to the vector, this changes the size
}
int main(void)
{
vector<int> v;
cout << "reserve and write\n";
v.reserve(10); // this does not change size, the vector is still empty
write_seq(v, v.capacity());
cout << "seq length " << v.size() << "\n";
return 0;
}
You cannot assign to an element that does not exist. Allocating memory is not sufficient, but your code is fine when you resize the vector (or create it with sufficient elements):
int main(void)
{
vector<int> v(10); // vector with 10 element
write_seq(v.data(), v.size()); // write to those 10 element
cout << "seq length " << v.size() << "\n"; // size is (still) 10
return 0;
}
Note that your code is not very idomatic. I assume you have reasons for that, but passing iterators to write_seq would be much more natural.
So, I have the following code in c++:
This is the 2d vector:
vector<vector<int>> adj;
Initialization of 2d vector:
adj[0].push_back(1);
adj[0].push_back(2);
adj[1].push_back(3);
adj[1].push_back(4);
adj[1].push_back(5);
Printing the vector:
for(auto i : adj) {
for(auto j : i)
cout << j << " ";
cout << endl;
}
Compilation is without error but when I try to run it shows nothing.
How to fix this?
When you write adj[0], you're implicitly assuming that the vector has a size of at least 1, in order for the zeroth element to exist. This is not the case for an empty vector, such as a newly initialized one. Unfortunately, this does not guarantee an error of any kind, it is Undefined Behavior, and the compiler is allowed to let literally anything happen. To avoid it, you need to make room for those elements, which can be done in a number of ways:
adj.resize(2); // now size == 2, and [0] and [1] can be safely accessed
adj[0].push_back(1);
adj[1].push_back(3);
or alternatively
adj.push_back({}); // append default-constructed vector
adj.back().push_back(1); // append 1 to the above vector
or, perhaps most concisely:
adj = {
{1, 2},
{3, 4, 5}
};
// adj now contains two vectors containing {1, 2} and {3, 4, 5} respectively
If you want to use the subscript [] operator for indexed access to a vector, consider using vector.at(), which performs the same functionality but throws an exception if the index is out of range. This can be very helpful for debugging.
You can initialize the size of the vector by calling its constructor:
vector< vector<int> > adj(row_size, vector<int>(col_size));
^^^ ^^^^^^^ ^^^
Dimension 1 Element Ctor Dimension 2
Then you can index it like an array.
std::vector operator[] expects an element to exist. It will result in undefined behavior if an undefined element is accessed. Push a std::vector to the outer vector before pushing int to the inner vector. The at() member can be used to safely access any array index with error handling.
#include <vector>
#include <iostream>
int main()
{
std::vector<std::vector<int>> adj(2); // add two std::vector<int>
adj[0].push_back(1);
adj[0].push_back(2);
adj[1].push_back(3);
adj[1].push_back(4);
adj[1].push_back(5);
for(auto const & i : adj) {
for(auto const & j : i)
std::cout << j << " ";
std::cout << std::endl;
}
}
int *tthousand = new int[10000];
int *hthousand = new int[100000];
static int tmillion[10000000];
Hello there,
I'm trying to dynamically allocate memory for a series of arrays. These arrays are then populated with random numbers ranging from 0 to 10,000,000. From there, they are sorted using a quicksort/selection sort. The problem I'm running into is that whenever the "tmillion" array is reached, the program will run for a time and then a stack overflow occurs.
I've tried writing it as:
int *tmillion = new int[10000000];
and..
static int tmillion[10000000];
I must be missing something simple. Apologies, I'm still a bit new to C++.
Thoughts?
Just for future reference. Since C++11 std::array was introduced in Standard Library. It should be preferred than C-like built-in array.
Example:
#include <array>
std::array<int, 10000000> myArray;
// fill the array with data
std::sort(myArray.begin(); myArray.end()); // sorts data using default operator <
More information about this container can be found on Bjarne homepage: http://www.stroustrup.com/C++11FAQ.html#std-array
The standard container array is a fixed-sized random-access sequence of elements defined in . It has no space overheads beyond what it needs to hold its elements, it does not use free store, it can be initialized with an initializer list, it knows its size (number of elements), and doesn't convert to a pointer unless you explicitly ask it to. In other words, it is very much like a built-in array without the problems.
Additional example:
#include <array> // std::array
#include <algorithm> // std::sort
#include <iostream> // std::cout
int main()
{
std::array<int, 10> myArray = {8, 3, 6, 7}; // array with 10 elements but create it with declaring only first 4 elements
std::cout << "BEFORE SORT:" << std::endl;
for (const auto& element : myArray)
{
std::cout << element << std::endl;
}
std::sort(myArray.begin(), myArray.end()); // sorts data using default operator <
std::cout << "AFTER SORT:" << std::endl;
for (const auto& element : myArray)
{
std::cout << element << std::endl;
}
}
Output:
BEFORE SORT:
8
3
6
7
0
0
0
0
0
0
AFTER SORT:
0
0
0
0
0
0
3
6
7
8
I'm new to c++ and programming in general. Feel free to leave any hints, tips, or suggestions about my code!!
I am trying to copy my doubles from a vector to an array. I used copy() and it is copying all the elements except for the last. So the last element in the array stays exactly the same as it was before I used copy. So when I try to add the sums of the elements in the array, I don't get the correct sum.
Here is my code:
vector<double> myVector;
double myArray[4];
double myDouble = 0.0;
...//(add elements to vector)
copy(&myVector[0], &myVector[4], myArray);
for(int i = 0; i < 4; i++)
{
myDouble += myArray[i];
if(i == 4)
cout << "The sum of your values is " << fixed << setprecision(2) << myDouble << endl;
}
Thank you! Let me know if I need to be more specific.
The call to std::copy() copies four elements. This seems to fill your array. Note that your array contains exactly 4 elements and the last valid index is 3. Your vector myVector seems to include at least 5 elements: If it contains less then 5 elements, the expression myVector[4] is illegal. That said, the end iterator in a sequence always refers to the element behind the last value of the sequence, i.e., sequences are half-open: the begin is included, the end is the first element not included.
That said, you probably want to copy like this:
std::copy(myVector.begin(), std::min(4, myVector.size()) + myVector.begin(), myArray);
Of course, to get the sum of the elements in the vector you would actually use
double sum = std::accumulate(myVector.begin(), myVector.end(), 0.0);
Copy all elements from your vector this way:
copy(myVector.begin(), myVector.end(), myArray);
You have this code:
copy(&myVector[0], &myVector[4], myArray);
It copies 4 elements.
Now you have the decalaration of the destination array:
double myArray[4];
So the array has 4 elements.
It seems that you want to copy all but the last element, so copy just 3 elements:
copy(&myVector[0], &myVector[3], myArray);