Inner-loop using vector.size() leads to infinite loop - c++

I am trying to avoid copying with vectors, so I am (I know -- poor practice) mutating the vector while I loop over it, but I have noticed that it evaluates size() at every loop end. Furthermore, even if I declare it outside of the loop and assign it to another variable, it still reevaluates. Even more surprising, even if I declare it const, it reevaluates. Can someone tell me why this is the case? And what is the best way to add to a vector without creating a separate one, then combining them after each inner loop completes? Sample code:
#include <vector>
int main()
{
std::vector<int> v {0};
// infinite loop
for (int i = 0; i < 100; ++i)
{
const size_t sz = v.size();
for (size_t j = 0; j < sz; ++j)
v.push_back(i);
}
return 0;
}

I believe you are trying to avoid memory reallocation with vectors.
If this is the case you should use reserve(n): it preallocate memory for n elements thus avoiding memory reallocation while it have n elements or less. When you reach n+1 elements it may reallocate.
I'd like to ask you to be more specific: what are you expecting from your code?

Related

is initializing an n-dimensional vector with constructor bad?

So, I recently figured out, that we can initialize an n sized vector with default values by writing e.g. vector<int> x(n, default_value).
This can also be applied to n dimensional vectors, e.g. n=3:
vector<vector<vector<int>>> x(n, vector(n, vector(n, default_value)))
Has this approach any advantages or disadvantages over doing:
vector<vector<vector<int>>> x;
x.resize(n);
for (int i = 0; i < n; i++)
{
x[i].resize(n);
for (int j = 0; j < n; j++)
{
x[i][j].resize(n);
}
}
The first one first creates default_value for each vector and then copies it to the destinations, so you get (n+1)^k allocations instead of n^k.
You forgot to initialize the integer-based vector. Therefore I argue the first version is less error-prone ;) It's also much cleaner and shows the intention clearly.
Although second could benefit from for(auto& c:vec) loops instead of indices. Or std::for_each, or any other loop-hiding stuff... Anyway you are doing initialization -> just use constructors.

I use the [] method to assign values, and the data can be printed out through std::cout, but why does size() return 0? [duplicate]

There is a thread in the comments section in this post about using std::vector::reserve() vs. std::vector::resize().
Here is the original code:
void MyClass::my_method()
{
my_member.reserve(n_dim);
for(int k = 0 ; k < n_dim ; k++ )
my_member[k] = k ;
}
I believe that to write elements in the vector, the correct thing to do is to call std::vector::resize(), not std::vector::reserve().
In fact, the following test code "crashes" in debug builds in VS2010 SP1:
#include <vector>
using namespace std;
int main()
{
vector<int> v;
v.reserve(10);
v[5] = 2;
return 0;
}
Am I right, or am I wrong? And is VS2010 SP1 right, or is it wrong?
There are two different methods for a reason:
std::vector::reserve will allocate the memory but will not resize your vector, which will have a logical size the same as it was before.
std::vector::resize will actually modify the size of your vector and will fill any space with objects in their default state. If they are ints, they will all be zero.
After reserve, in your case, you will need a lot of push_backs to write to element 5.
If you don't wish to do that then in your case you should use resize.
One thing about reserve: if you then add elements with push_back, until you reach the capacity you have reserved, any existing references, iterators or pointers to data in your vector will remain valid. So if I reserve 1000 and my size is 5, the &vec[4] will remain the same until the vector has 1000 elements. After that, I can call push_back() and it will work, but the stored pointer of &vec[4] earlier may no longer be valid.
It depends on what you want to do. reserve does not add any
elements to the vector; it only changes the capacity(), which
guarantees that adding elements will not reallocate (and e.g.
invalidate iterators). resize adds elements immediately. If you want
to add elements later (insert(), push_back()), use reserve. If you
want to access elements later (using [] or at()), use resize. So
youre MyClass::my_method can be either:
void MyClass::my_method()
{
my_member.clear();
my_member.reserve( n_dim );
for ( int k = 0; k < n_dim; ++ k ) {
my_member.push_back( k );
}
}
or
void MyClass::my_method()
{
my_member.resize( n_dim );
for ( int k = 0; k < n_dim; ++ k ) {
my_member[k] = k;
}
}
Which one you chose is a question of taste, but the code you quote is
clearly incorrect.
There probably should be a discussion about when both methods are called with a number that's LESS than the current size of the vector.
Calling reserve() with a number smaller than the capacity will not affect the size or the capacity.
Calling resize() with a number smaller than current size the container will be reduced to that size effectively destroying the excess elements.
To sum up resize() will free up memory whereas reserve() will not.
Yes you’re correct, Luchian just made a typo and is probably too coffee-deprived to realise his mistake.
resize actually changes the amount of elements in the vector, new items are default constructed if the resize causes the vector to grow.
vector<int> v;
v.resize(10);
auto size = v.size();
in this case size is 10.
reserve on the other hand only requests that the internal buffer be grown to the specified size but does not change the "size" of the array, only its buffer size is changed.
vector<int> v;
v.reserve(10);
auto size = v.size();
in this case size is still 0.
So to answer your question, yes you are right, even if you reserve enough space you are still accessing uninitialized memory with the index operator. With an int thats not so bad but in the case of a vector of classes you would be accessing objects which have not been constructed.
Bounds checking of compilers set to debug mode can obviously be confused by this behavior which may be why you are experiencing the crash.

C++ : How to safely deallocate a heap-allocated array of vectors?

I am currently working with code that at the moment requires me to make an array of vectors (I am new to C++ - if this is an absolutely terrible idea, I would greatly appreciate the feedback).
Let's say I allocate memory on the heap for my vectors like so:
#include <iostream>
#include <vector>
#include <random>
int main() {
typedef std::vector<double> doubleVec;
long N = 1000;
long M = 1000;
doubleVec *array = new doubleVec[N];
for (long i = 0; i < N; i++) {
doubleVec currentVec = array[i];
currentVec.resize(M);
for (long j = 0; j < M; j++)
currentVec[j] = std::rand();
}
// ... do something with the data structure
delete [] array;
}
When I've done everything I need to do with the data, how should I safely deallocate this data structure?
NOTE: There were other things I did wrong in my inital post that I didn't intend to be the focus of the discussion (uninitialized variables, didn't resize vectors, etc). I fixed those now. Thank you all for pointing those out.
f this is an absolutely terrible idea, I would greatly appreciate the feedback).
Yes, this is a terribly bad idea. To be specific, owning bare pointers are a bad idea. Instead of manually allocating a dynamic array, it is usually better to use a container such as std::vector.
How to safely deallocate a heap-allocated array of vectors?
By using a vector instead of manual dynamic array. In this case, a simple solution is to use a vector of vectors.
A potentially better solution would be to allocate a single flat vector of doubles of size 1000*1000 where elements of each "subvector" is after another. This requires a bit of simple math to calculate the index of the sub vectors, but is in most use cases faster.
Other notes:
typedef std::vector<double> doubleVec;
Avoid obfuscating the program by hiding type names like this.
for (long j; j < M; j++)
^^^^^^
You leave this variable uninitialised. When the indeterminate value is used later, the behaviour of the program is undefined.
Furthermore, you forgot to include the standard headers which define std::vector and std::rand.
I got a seg fault
See the other answer regarding you not actually adding any elements to the vectors that are in the array. This, and the uninitialised variables are the most likely reason for your segfault depending on what "do something" does.
The problem is not in deallocating but in each vector allocation. Where in your code do you use the M value (except while accessing the elements)? There are other problems in your code, so the quick fix is:
for (long i; i < N; i++) {
doubleVec &currentVec = array[i];
currentVec.resize(M);
for (long j; j < M; j++)
currentVec[j] = std::rand();
}
Pay special attention that currentVec is a reference: otherwise no changes would be stored in the array.
Anyway, the main question everybody would have is: why do you need to have an array of vectors?.. The vector of vectors is a much more elegant solution.
Update: I've missed the fact that you have forgotten to initialize both i and j. In addition to the advice to initialize them I would recommend to use the auto keyword that would make it impossible to leave the variable uninitialized:
for (auto i=0UL; i < N; i++) {
doubleVec &currentVec = array[i];
currentVec.resize(M);
for (auto j=0UL; j < M; j++)
currentVec[j] = std::rand();
}
0UL means zero of the type unsigned long.

Fill/Initialize vector with Objects in C++ [duplicate]

There is a thread in the comments section in this post about using std::vector::reserve() vs. std::vector::resize().
Here is the original code:
void MyClass::my_method()
{
my_member.reserve(n_dim);
for(int k = 0 ; k < n_dim ; k++ )
my_member[k] = k ;
}
I believe that to write elements in the vector, the correct thing to do is to call std::vector::resize(), not std::vector::reserve().
In fact, the following test code "crashes" in debug builds in VS2010 SP1:
#include <vector>
using namespace std;
int main()
{
vector<int> v;
v.reserve(10);
v[5] = 2;
return 0;
}
Am I right, or am I wrong? And is VS2010 SP1 right, or is it wrong?
There are two different methods for a reason:
std::vector::reserve will allocate the memory but will not resize your vector, which will have a logical size the same as it was before.
std::vector::resize will actually modify the size of your vector and will fill any space with objects in their default state. If they are ints, they will all be zero.
After reserve, in your case, you will need a lot of push_backs to write to element 5.
If you don't wish to do that then in your case you should use resize.
One thing about reserve: if you then add elements with push_back, until you reach the capacity you have reserved, any existing references, iterators or pointers to data in your vector will remain valid. So if I reserve 1000 and my size is 5, the &vec[4] will remain the same until the vector has 1000 elements. After that, I can call push_back() and it will work, but the stored pointer of &vec[4] earlier may no longer be valid.
It depends on what you want to do. reserve does not add any
elements to the vector; it only changes the capacity(), which
guarantees that adding elements will not reallocate (and e.g.
invalidate iterators). resize adds elements immediately. If you want
to add elements later (insert(), push_back()), use reserve. If you
want to access elements later (using [] or at()), use resize. So
youre MyClass::my_method can be either:
void MyClass::my_method()
{
my_member.clear();
my_member.reserve( n_dim );
for ( int k = 0; k < n_dim; ++ k ) {
my_member.push_back( k );
}
}
or
void MyClass::my_method()
{
my_member.resize( n_dim );
for ( int k = 0; k < n_dim; ++ k ) {
my_member[k] = k;
}
}
Which one you chose is a question of taste, but the code you quote is
clearly incorrect.
There probably should be a discussion about when both methods are called with a number that's LESS than the current size of the vector.
Calling reserve() with a number smaller than the capacity will not affect the size or the capacity.
Calling resize() with a number smaller than current size the container will be reduced to that size effectively destroying the excess elements.
To sum up resize() will free up memory whereas reserve() will not.
Yes you’re correct, Luchian just made a typo and is probably too coffee-deprived to realise his mistake.
resize actually changes the amount of elements in the vector, new items are default constructed if the resize causes the vector to grow.
vector<int> v;
v.resize(10);
auto size = v.size();
in this case size is 10.
reserve on the other hand only requests that the internal buffer be grown to the specified size but does not change the "size" of the array, only its buffer size is changed.
vector<int> v;
v.reserve(10);
auto size = v.size();
in this case size is still 0.
So to answer your question, yes you are right, even if you reserve enough space you are still accessing uninitialized memory with the index operator. With an int thats not so bad but in the case of a vector of classes you would be accessing objects which have not been constructed.
Bounds checking of compilers set to debug mode can obviously be confused by this behavior which may be why you are experiencing the crash.

Segmentation fault: 11 c++ when using vector

i am trying to write a program for my university project the program is supposed to do first come first serve scheduling i have thought a lot about this function but i don't know how to make it work, i always get Segmentation fault: 11, i also tried to use temp.at(j) but it gave me Segmentation fault: 6, and i tried to minimise the vector so it would be in-bound by declaring the vectors outside the function, then use temp.size() instead of Processes but it also did't work.
void FCFS(Process ProcessDetails[], int Processes)
{
vector<int> temp;
vector<int> temp1;
int first = 0; //first value to compare with.
for(int j = 0; j < Processes; j++){ // to make sure that it passes through all elements.
for(int i = 0; i < Processes; i++){ // pass each PID and Burst time to vector temp and temp1.
if(ProcessDetails[i].ArrivalTime == first){
temp.operator[](j) = ProcessDetails[i].PID;
temp1.operator[](j) = ProcessDetails[i].BurstTime;
}
}
first++;// increase first value to declare the round is finished and start a new one.
}
for(int i = 0; i < Processes; i++){ // pass the sorted vector values back to the arrays.
ProcessDetails[i].PID = temp.operator[](i);
ProcessDetails[i].BurstTime = temp1.operator[](i);
}
}
the program works fine until it reaches this function, please help.
The behaviour of a vector's operator[]() is undefined if it is used to access elements that do not exist.
Since you have used default-constructed vectors, their size is zero - so they have no elements to access.
If you use the .at() member function, it will check the index and throw an exception (of type std::out_of_range, which is declared in the standard header <stdexcept>) when indices are invalid. You can confirm that by wrapping the code in an appropriate try/catch block.
To eliminate the problem, you need to reize the vector (e.g. add elements to it using push_back(), resize it using resize(), etc) before using operator[](). And ensure the index is valid, since operator[]() does not resize a std::vector.
Also, temp[j] is equivalent to temp.operator[](j). For types that supply an operator[]() function, the compiler handles turning expressions like temp[j] into a call of temp.operator[](j).
Your vectors have no elements.
Using the vector operator[] will therefore fail.
Use push_back, emplace, resize, or some other function to add elements to the vectors.
you will have to change your vector assignment to
if(ProcessDetails[i].ArrivalTime == first){
temp.push_back(ProcessDetails[i].PID);
temp1.push_back(ProcessDetails[i].BurstTime);
}