Is it possible to initialize new position of vector using array without push_back (C++ STL) - c++

While I was doing experiment with vector in C++, I was facing some strange problem. May be it was because of my little knowledge of C++ STL. I am using Code::Blocks 16.01 IDE having GNU GCC compiler in it.
When I run this code:
vector <int> vec;
vec.push_back(66);
vec.push_back(12);
cout << vec[1] << endl;
The output is obviously correct i.e. 12.
Again, when I run this code:
vector <int> vec;
vec.push_back(66);
vec.push_back(12);
vec[1] = 18;
cout << vec[1] << endl;
This time the output is also correct i.e. 18.
This time I did push_back() for only first 2 elements of vector. But initialized the value of 6th element using array and after running the following code:
vector <int> vec;
vec.push_back(66);
vec.push_back(12);
vec[5] = 18;
cout << vec[5] << endl;
The output is again fine i.e. 18.
But, when I run the code below, the console window crashes immediately. I don't know why.
vector <int> vec;
vec.push_back(66);
vec.push_back(12);
cout << vec[1] << endl;
vec[5] = 18;
cout << vec[5] << endl;
Once I used cout once, the program crashes. Why this is happening? Am I missing something about the connection of vector with array? I want to know the proper way to handle vector using array or is it bad practice to use array to handle vector?

Am I missing something about the connection of vector with array?
No you do not. If you misbehave the same way with array you will have the same issue:
int array[2];
array[5] = 18; // this is undefined behaviour
std::cout << array[5] << std::endl; // this is undefined behaviour as well
you can even see desired output in some environment, but it could crash on another, or start to crash when you change your code. That is problem with UB - it is unpredictable. And accessing elements out of range has similar consequences with array and std::vector, difference - you can resize std::vector but cannot do that to array.

When you access an element of a std::vector that is outside of the size of the vector, you get undefined behavior. Undefined behavior means what it sounds like - anything could happen. This is why sometimes your program will crash, and other times it works fine. You should not rely on undefined behavior for anything, instead you should resize your vector using std::vector::resize before inserting something outside of the size of the vector.

Related

How does C++ handle vectors when passing from a function to main?

I'm seeing strange behaviour in the output of a 'simple' function that generates the binary representation of an integer. I aim to use the function in another code, but first want to see it working by printing to the console. I first define the function dec2bin to take a number and the length of the required bitstring. After defining a vector that will be returned by the function, the vector is populated with the required binary values. In the main function, the vector is accessed and printed element-wise to the console. However, the output is incorrect unless I include an arbitrary cout statement within the vector populating for loop.
The function is defined as follows:
vector<int> dec2bin(int N, int j){
vector<int> myvec;
myvec.push_back(N);
for (int i = N-1; i >= 0; i--) {
int r = j >> i;
if (r & 1)
myvec[N-i-1] = 1;
else
myvec[N-i-1] = 0;
//cout << " ";
}
return myvec;
}
My main function is:
int main(){
int length = 8;
int num = 15;
vector<int> myvec = dec2bin(length,num);
for (int j=0; j<length; j++){cout << myvec[j];}
return 0;
}
When the commented out line (cout << " ") is included within the for loop the output is correct, with 00001111. Without that line (or with the line outside of the for loop) the output is incorrectly 00001141130.
I have read various things about pointers and memory allocation, so expect this is where I am going wrong; however, I can't quite see how to incorporate those ideas into my own code. Any advice would be greatly appreciated, many thanks.
On this line:
myvec[N-i-1] = 1;
You are invoking undefined behavior for any index other than 0.
myvec.push_back(N); pushes a single element to the vector, and you never add more elements to the vector. When you access a vector out of bounds, you will not get a compiler error or runtime exception, but your code has undefined behavior, which means the output could be literally anything.
Actually, it seems like you just confused push_back() with resize(). And instead of resize(), you can pass the size to the constructor. If you replace:
vector<int> myvec;
myvec.push_back(N);
with:
std::vector<int> myvec(N);
or:
std::vector<int> myvec;
myvec.resize(N);
You get a vector with N elements, and accessing myvec[i] is fine for any index 0 <= i < N. Alternatively, you could call myvec.reserve(10) to let the vector allocate space for N elements. The vector will then still be empty, and you have to push_back() any element you want to add.
You are accessing the unallocated memory because you only pushed back(push_back()) once and due to it you are getting undefined behaviour.
You should use .at() function instead of [] operator for accessing the vector element, it'll throw the exception out of bounds.
You need to use push_back() for insertion into the vector or you can use vector.resize(size) during vector declaration then it'll save you from undefined behavior.
Thanx

Why are vectors' size static and we still can add more values?

I'm a complete beginner to C++ but I have some basics knowledge in programming (Python mainly) and I'm trying to learn C++. As the question implies, vectors have static sizes (at least what I've read in my learning material) but we still can add more values to what the size authorize. I wrote a simple code to know what error I get if I pass more values to a vector than the limit authorized by it's size and surprisingly I didn't get any error.
The code are these simple lines:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int it=0,a;
vector<int> v(10);
for(a=1; a<21; a++)
{
v[it]=x;
cout << v[it] << endl;
it++;
}
cout<<"Values stored in v";
for(i=0;i<it;i++)
cout<<v[i]<<" ";
cout<<endl;
cout<<"Vector's size : "<<v.size()<<endl;
return 0;
}
What I get with cout<<"Values stored in v"; are all values from 1 to 20, but I still get that the size is 10.
If that can helps I'm on Windows 10 x64 and using Qt Creator compiler.
What is fixed is
sizeof( vector<int> )
A vector can contain varying number of elements, but that elements are stored on the heap, hence do not contribute to the vectors sizeof. The number of elements is v.size() (and that can change).
You create a vector with 10 elements:
vector<int> v(10);
But then you attempt to access elements that do not exist in the loop. For example v[10] will not cause a compiler error, it is also not guaranteed to cause a runtime error. Nevertheless, it is guaranteed wrong. Accessing the vector out of bounds causes undefined behavior. The output of the code could be anything.

what does vector.size mean?

I wonder about this code
vector<pair<int,int>> map;
std::cout << "hello"<< std::endl;
map.push_back(make_pair(1,2));
map.push_back(make_pair(3,4));
map.push_back(make_pair(5,6));
map.resize(0);
std::cout << map[0].first
<< map[0].second << std::endl;
std::cout << map[2].first << std::endl;
std::cout << map.size() << std::endl;
std::cout << map.capacity() << std::endl;
I resize the map to size 0, but the result shows like this:
hello
12
5
0
4
Why do I get this?
Size of the vector (objects it contains) is not necessarily equal to its capacity (storage space allocated for it)
Looking at http://www.cplusplus.com/reference/vector/vector/size/, you can notice this statement: "This is the number of actual objects held in the vector, which is not necessarily equal to its storage capacity."
If you check you can see the following: http://www.cplusplus.com/reference/vector/vector/capacity/ "This capacity is not necessarily equal to the vector size. It can be equal or greater, with the extra space allowing to accommodate for growth without the need to reallocate on each insertion."
I hope this answers your question
Besides the thing about the vector capacity in the other answer, accessing out of bounds indexes on vectors with the bracket operator (instead of at(), which provides bound checking) produces undefined behavior.
In other words, the behavior is not defined in the standard and can change based on things like your compiler. In your case, it apparently did not crash and outputted the values even after they're no longer in the vector.
Needless to say, you want to make sure your program is free of undefined behavior.

Adding vector to 2D vector, and keeping reference to the last vector

I am writing a program and there was a very subtle error that was hard to recognize.
I examined the program for hours and it looks like it's from my misuse of resize() in allocating a new vector in 2D vector, from my misuse of back() in vector, or from updating a reference variable.
I wrote a simpler code that contains similar problem in my original program for demonstration:
int main() {
vector<vector<int>> A(1);
vector<int> &recent = A.back();
recent.emplace_back(50);
cout << A.back()[0] << endl; //prints 50
A.resize(2);
A[1] = vector<int>();
cout << A.size() << endl; //prints 2
recent = A.back();
cout << A[1].size() << endl; //prints 0
recent.emplace_back(20); //Segmentation fault occurs!!
cout << A[1][0] << endl;
}
Segmentation fault occurs when I tried to emplace_back(20), although in my original program it doesn't throw any error and doesn't emplace the element either.
Possible cause of problem, in my opinion is:
I used resize() to allocate a new vector after the current last position of the 2D vector A, because I didn't know how to emplace_back() an empty vector.
2, 3. In recent = A.back();, I'm not sure if I am updating the reference variable(defined as vector<int> &recent) correctly, and if back() gives the correct reference to the newly allocated vector at the end of the 2D vector A.
The logic looked perfectly fine, but obviously I am doing something wrong.
What am I doing wrong, and what can I do instead?
References in C++ cannot be "updated". The call to resize may (and likely will) invalidate any reference to the original content of the vector. Thus recent is a dangling reference after A.resize(2);.
When creating the initial A here
std::vector<std::vector<int>> A(1);
the outer vector is required to be able to store one single vector.
If you add another std::vector<int> to A the first element of A is likely to move to another memory location. Since recent will always refer to the old memory location you see the segfault.
See 'c++ Vector, what happens whenever it expands/reallocate on stack?' for how vectors work.
On the question how to circumvent this:
If you know the size of the vector in advance you could use reserve to prevent the vector A from reallocating its contents. You'd nevertheless face the problem that references cannot be "reassigned". You can always use A.back() to refer to the last element.
You can use a function taking a reference argument which will be bound upon calling the function:
void do_stuff(std::vector<int> & recent)
{
// do stuff with recent
}
std::vector<std::vector<int>> A;
while (condition)
{
// add whatever to A
A.emplace_back(std::vector<int>{});
// do stuff with last element
do_stuff(A.back());
}
Another way to do it is with scope:
std::vector<std::vector<int>> A(1);
{
std::vector<int> &recent = A.back();
recent.emplace_back(50);
std::cout << A.back()[0] << std::endl; //prints 50
A.resize(2);
} // recent goes out of scope here
std::cout << A.size() << std::endl; //prints 2
{
std::vector<int> &recent = A.back(); // another recent indepedant of first one
std::cout << A[1].size() << std::endl; //prints 0
recent.emplace_back(20);
std::cout << A[1][0] << std::endl; // prints 20
}
Let's step through the code line by line.
vector<vector<int>> A(1);
vector<int> &recent = A.back();
Here we create a vector with one default-constructed vector<int> as its contents. We then bind a reference to the last and only element.
recent.emplace_back(50);
cout << A.back()[0] << endl; //prints 50
We now emplace 50 into the sole vector and print it.
A.resize(2);
Now we resize the vector. If space needs to be reallocated, all iterators, pointers and references to the contents are now invalid.
A[1] = vector<int>();
cout << A.size() << endl; //prints 2
This is fine, as there is enough space in A.
recent = A.back();
BANG
This assignment doesn't rebind recent, it tries to assign A.back() to the referencee. If space was reallocated for A, recent is no longer a valid reference, so we run off into the realm of undefined behaviour.
Quite honestly, using A.back() directly rather than maintaining a reference to it is probably your best bet. If you absolutely want to hold some kind of reference to the end, this is a reasonable use of a non-owning pointer.
From the discussion in the comments, it appears that your original problem was:
vector<vector<int>> very_long_name_that_cannot_be_changed;
and that you want a shorthand notation to access the last element of this:
auto& short_name = very_long_name_that_cannot_be_changed;
short_name.resize(100); // will expand the vector, but not change the reference
short_name.back().emplace_back(20); // presto, quick accesss to the last element.
This is proof against resizing, because the reference just tracks the vector, not its last element.

Vector <int> input and output

I am stuck with simple vector input and output operations. The compiler returns error saying 'std::outof range'
Here is the code
int main()
{
int size;
cout <<"Enter size of vector\n";
cin>>size;
cout<<"Now to input the vector of size "<<size<<endl;
vector <int> trial;
for (size_t i=0;i<size;++i){
int x;
cout<<"write at position"<<trial.at(i)<<'t';
cin>>x;
trial.push_back(x);
cout<<endl;
}
ostream_iterator<int> output(cout,"");
copy(trial.begin(),trial.end(),output);
}
I would appreciate a brief explanation of the internal workings of the problem.
You invoke trial.at(i) before trial.push_back(x), accessing a not yet existing element. Since the element doesn't (yet) exist, i is an invalid index, and at() will throw a std::out_of_range exception when passed an invalid index. If an exception isn't caught, it will terminate the program. Presumably your platform's runtime library displays the exception that caused the program to be terminated.
I suppose what you actually want is this:
std::cout << "write at position " << i << '\t';
Consider the first iteration of this loop:
vector <int> trial;
for (size_t i=0;i<size;++i){
int x;
cout<<"write at position"<<trial.at(i)<<'t';
At the first iteration nothing has been pushed into the vector, so trial.at(0) isn't yet valid. The result will be an exception. Since you don't have a try/catch anywhere, that will end your program's execution.
It looks to me like you want cout << "write at position " << i; instead. i is the position; after it has been pushed onto the vector so it's valid, vector.at(i) will be the value at that position.
trial.at(i)
You're accessing an element that doesn't exist.
You probably want cout<<"write at position"<< i <<'t'; anyway.
The problem is this line:
cout<<"write at position"<<trial.at(i)<<'t';
You call this before you have set the size of the vector. I'm not really sure what that line is trying to accomplish anyway. If you're trying to print the in memory position (address) that won't do it, if you're trying to print what was already there then it would work if it had already been allocated. Using vector::push_back() means that you don't need to preallocate though.
You can fix this by resizing the vector and accessing the elements directly like this:
trial.resize(size);
// loop
// vector.push_back(x) -- now becomes
vector[i] = x;
Or, you can simply remove the printing of the position and use push_back() as you are now.
Since it seems you're investigating how to use vector I would suggest trying to gain an understanding of how the push_back() and resize() methods differ, and have also have a look at the vector::reserve() function.