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

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.

Related

Why does my array say write access violation partially through?

Updated to be copy/pasted and run. My bad.
I know I'm probably going to get the whole "this question was asked already" but I spent sometime looking and couldn't find a matching problem. It's very possible I just don't know enough to look in the right place.
When I call InitSortedArray() it runs through a seemingly random number of elements before throwing exception: write access violation. Everytime I run it it stops at a different element number. Any ideas?
#include <array>
#include <iostream>
using namespace std;
int * toSort;
const int SIZE = 100000;
void InitSortedArray()
{
srand(0);
toSort[0] = rand() % 5;
cout << toSort[0];
for (int i = 1; i < SIZE - 1; i++)
{
srand(0);
toSort[i] = toSort[i - 1] + rand() % 5;
cout << toSort[i] << endl;
}
}
void Search()
{
toSort[SIZE];
InitSortedArray();
}
int main()
{
Search();
}
int * toSort;
allocates a pointer to some data yet to be assigned to it. No data is ever assigned. You could
int * toSort = new int[100000];
but that picks up some memory management work you don't need. Any time you use new[] sooner or later you must delete[]. Instead use
const int SIZE = 100000; // place first so we can use it below
int toSort[SIZE];
or the more modern
const int SIZE = 100000; // place first so we can use it below
std::array<int, SIZE> toSort;
to declare an array.
toSort[100000];
in Search does nothing helpful (and is in fact harmful as it invokes Undefined Behaviour by accessing outside the bounds of toSort) and should be removed.
Extra stuff:
srand reseeds and restarts the random number generator. It is only in truly rare circumstances that you want to call it more than once, and in those cases there are many better options than srand and rand.
Place a single call to srand at the top of main and make absolutely certain you want srand(0) as this will always generate the exact same numbers on a given computer. It's great for testing, but not so good if you want a different sequence every time. Typical use is srand(time(NULL)) to seed the generator based on the ever-changing flow of time. That's still not all that good, but good enough for most cases where rand is in use.
It looks like you're using an uninitialized pointer that points to random space, and trying to store elements and access elements in it. Also, your inclusion of "array" doesn't make any sense here. I believe what you want to do here is initialize your toSort array to actually point to a section of memory that you intend to point it to:
int toSort[SIZE];
instead of
int * toSort;
If you're looking to use the STL array (which is likely highly recommendable) then you need to explicitly use it:
std::array<int, SIZE> toSort;
The nice thing about using the STL is it takes care of a lot of the memory access issues you can run into like memory access violation. Another helpful thing from the STL would be vector:
#include <vector>
std::vector<int> toSort;
then later: (this adds an item to the back of the vector)
toSort.push_back(<some number>);
and to access:
int somethingElse = toSort[<index number>];
Arrays: http://en.cppreference.com/w/cpp/container/array
Vectors: http://en.cppreference.com/w/cpp/container/vector

Trying to read file which contains ints and store in int vector, but I keep getting "Segmentation fault (core dumped)" error

So I made this practice file for my project to try and read a file containing integer numbers, and store them in an int vector. My problem is whenever I run the program, it will give me "Segmentation fault (core dumped)" during the call to the readFile() function.
Do not mind the extra imports, I just copy and paste the same imports to all my practice files. Also the cout << "hi" << endl; is just to see when the program has the error.
#include <string>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cassert>
#include <vector>
using namespace std;
vector<int> readFile(string fileName);
int main()
{
vector <int> intvec = readFile("ints.txt");
cout << "hi" << endl;
for (int i = 0; i < intvec.size(); i++)
{
cout << intvec[i] << endl;
}
return 0;
}
vector<int> readFile(string fileName)
{
ifstream inFile(fileName);
vector<int> inputVec;
int i = 0;
while (!inFile.eof())
{
inFile >> inputVec[i];
i++;
}
inFile.close();
return inputVec;
}
You would want to do this
while (inFile >> i)
{
inputVec.push_back(i);
}
In your code, you define inputVec without giving it an initial capacity, so you can assume that its size is 0. So when you write inputVec[i], you're actually trying to access an index out of the vector's boundaries. It's like accessing the 5th element in an array of size 4.
By using push_back, you can add elements to the vector and it'll adjust the size dynamically.
c++ std::vectors need to be resized before adding to them. Try the "push_back" function instead, that adds them on the end and resizes the vector to fit.
BTW unlike e.g. JavaScript you can't use "vector[i] == value" to automatically resize a c/c++ array/vector.
BTW, square brackets [] operator in c arrays and std::vector is completely different to that in JavaScript. JavaScript arrays are associative maps and using array[value] causes it to create a key "value" automatically. But this is extremely slow. The square brackets operators in c/c++ don't work like that. They are a much faster direct memory access system.
If you have an array called "myArray" and you asked for myArray[10], the computer just looks at whatever is inside the computers RAM 10 addresses beyond the start of myArray (multiplied by the size of the elements, so myArray[10] would be 40 bytes past the start of an array with 4-byte values such as int or float.
It's designed for pure speed, so there's no bounds checking added to this. it's entirely up to the c/c++ programmer to ensure that you don't read or write outside the bounds with square brackets operatork, but the payoff is much faster programs. You can add your own bounds checking to your own code, or you can just be careful not to read past the range you've allocated.
Using the std::copy algorithm and iterators, a vector can be filled with the following:
#include <fstream>
#include <iterator>
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> intvec;
std::ifstream ifs("ints.txt");
std::copy(std::istream_iterator<int>(ifs),
std::istream_iterator<int>(),
std::back_inserter(intvec));
}
Note: The std::back_inserter automatically calls push_back for each item in the stream.

is it possible to access an element within array of array?

i have an array b[i] which stores the certain indices of another array a[i];both are integer arrays
Is it possible to access it as
a[b[i]]
#include <iostream>
using namespace std;
int main()
{
int k=0,v=0,i,b[10],c[10];
int a[]={1,2,3,4,5,6,7,8,9,10};
for(i=0;i<10;i++){
if(a[i]%2==0)
{b[k]=i; k++;}
}
for(i=0;i<10;i++)
{
c[v]=a[b[i]];
v++;
}
return 0;
}
results in segmentation fault
In your second loop, the b array is only half initialized (once for every even number from 1 to 10) so when you try to dereference b[5] you get undefined behavior and hence a segfault
It works fine until you get to i = 5 for the second loop. When i = 5, a[b[5]] is undefined because b[5] is uninitialized. After the first loop, you have b[] = {1, 3, 5, 7, 9, ....} the rest is uninitialized. Try to initialize b[10] and it should work.
b[10] = {};
This method should work:
a[b[i]];
I'm not 100% sure it will work though, because the compiler has a role to play here too. For example, it works perfectly in TC++...
A better way to do it is this:
for(i=0;i<10;i++)
{
int temp=b[i];
c[v]=a[temp];
v++;
}
Here is the reason for the error you see:
'Segmentation fault' in this case means that you used a[] array index well beyond a value within memory available to the process (note: it does not need to be beyond the memory range of your computer to get this error; also note that using indexes slightly bigger than array size usually do not cause segmentation faults; but such index value is still a semantic error, of course).
When you declare b[], you do not initialize it (and that is usual).
Your first loop only initializes selected elements of b[]: only as much elements from the beginning of b[], as there are even numbers in a[] (you use the condition:a[i]%2==0).
Currently, you have 5 even numbers in a: 2,4,6,8,10. This is sufficient to initialize elements of b[0]...b[4]. The elements of b[] starting with b[5] are left uninitialized, i.e. contain numbers which can be considered random, or trash. You can print b[5]...b[9] to see what do they contain without initialization – it is often 0’s (making debugging even harder, because a[0] does not cause segmentation faults - but a[0] is probably not what you want to get in c[]).
But in different runs of your program elements of b[] starting with b[5] can be anything (and then any of them can make a segmentation fault, e.g. a[-2000000000]).
Chances are extremely low that these accidental values will represent valid indexes of a[].
Relief: change your SECOND loop so it runs only k times, not 10 times. This was probably your initial intention, anyway:
for(i=0;i<k;i++)
#include <iostream>
using namespace std;
int main()
{
int k=0,v=0,i,b[10],c[10];
int a[]={1,2,3,4,5,6,7,8,9,10};
for(i=0;i<10;i++){
if(a[i]%2==0)
{b[k]=i; k++;}
}
for(i=0;i<5;i++)
{
c[v]=a[b[i]];
v++;
}
return 0;
}
works well

Debug assertion failed.. C++ vector subscript out of range

The following code is supposed to remove the duplicate values in a vector.
For example, if vector contains {1,5,3,3} the result should be {1,5,3}.
The program starts and I enter the integer n*.
However, the program throws the following error:
Debug assertion failed.Program : ...\include\vector line:932
Expression:vector subscript out of range.
When I press retry, visual c++ displays a new window:
"try.exe has triggered a breakpoint".
Then, after I click on continue, another error appears:
Debug Assertion Failed! Program :...\include\vector line:933
expression:"standart c++ libraries out of range" && 0
My code is as follows:
#include <iostream>
#include <vector>
using namespace std;
void removeDup (vector<int>& v);
int main()
{
vector<int> v;
int i,n;
cin>>n;
for(i=0;i<n;i++){
v[i]=rand()%10;
}
removeDup(v);
for(i=0;i<n;i++)
{
cout<<v[i];
}
system("pause");
}
void removeDup(vector<int>& v)
{
int i,j,size;
size=v.size();
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
if(v[i]==v[j])
v.erase(v.begin()+j);
}
}
}
The assertion failure is actually telling you exactly what's happening. Your vector is zero-sized, and you are trying to index an empty one (which is naturally going to access things out of bounds).
operator[] does not create elements on the fly for a standard sequence like vector as with, say, associative arrays in some languages or as with the case of std::map. The index you pass to operator[] must be in the range, [0, vector.size()) or it will trigger this out of range assertion failure in debug (for checked implementations) or a potential segfault/access violation in a release build (basically undefined behavior). This is done for performance reasons as it would otherwise require branching in operator[], and that would typically destroy the array-comparable indexing performance that vector has (though there is an at method which throws which has the branching overhead).
Here you want to size the vector in advance using the fill constructor, ex:
int i,n;
cin>>n;
vector<int> v(n);
...
Or resize it prior to accessing it with operator[] using the resize method:
vector<int> v;
int i,n;
cin>>n;
v.resize(n);
Or use push_backs:
vector<int> v;
int i,n;
cin>>n;
// can use reserve here for a performance boost if desired
// since we know the memory capacity needed in advance.
for(i=0;i<n;i++){
v.push_back(rand()%10);
}
There is one other issue in your removeDup function. That one has an issue in that you are looping through the vector as though its size doesn't change, but calling an erase method which will reduce its size at every iteration. That will also invoke an out of range access -- there maybe you can figure out the solution as part of the exercise (I'm assuming this is an exercise since std::unique will do the trick). First thing to note here perhaps is that operator[] doesn't create elements for you on the fly.
I am giving you another way to solve this.(U may use it).
Here you can use #include<set> to remove the duplicate value like the following:
set<int>s;
s.insert(10);
int i,n;
cin>>n;
for(i=0;i<n;i++){
s.insert(rand()%10);
}
set<int>::iterator ii;
for(ii=s.begin();ii!=s.end();ii++)
cout<<*ii;

Array size allocation at compile time, expecting constant value [duplicate]

This question already has answers here:
Enabling VLAs (variable length arrays) in MS Visual C++?
(5 answers)
Closed 8 years ago.
// testing1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <vector>
#include <iostream>
#include<conio.h>
using namespace std;
struct Data_point {
double x;
double y;
};
void PlotThis(unsigned int n )
{
Data_point graph[n]; //shows error here
//do something else, dont worry about that
}
int main ()
{
unsigned int nSamples;
cout << "Please enter nSamples: ";
cin >> nSamples;
PlotThis(nSamples);
return 0;
}
This shows error when compiling:
Error 1 error C2057: expected constant expression testing1.cpp 23
Error 2 error C2466: cannot allocate an array of constant size 0 testing1.cpp 23
Error 3 error C2133: 'graph' : unknown size testing1.cpp 23
Line 23 is Data_point graph[n]; //shows error here
It is showing unknown size even though I am passing it the value from main(). It is asking for the value (the size of graph i.e n) at the compile time. Does that mean array size allocation takes place at compile time? How to solve this
C++ doesn't support arrays with size determined at run-time. You could switch to using the Vector class instead.
std::vector<Data_point > graph;
To follow the logic you're using: In PlotThis you could use std::vector::resize to resize the container to contain n elements.
void PlotThis(unsigned int n){
graph.resize(n); // Resize Vector container
...
Also with std::vector:
"compared to arrays, vectors consume more memory in exchange for
the ability to manage storage and grow dynamically in an efficient way."
This means you have the option to not worry about specifying the size of the vector and just adding elements as you need to. So you could have a loop determine how many elements are added (n) in your method - possible to use std::vector::push_back. If you do this then just make sure to clear the vector at some point so you don't re-use old data - possible to use std::vector::clear.
You can use some containers, for example vector, deque etc...
void PlotThis(unsigned int n)
{
std::vector<Data_point> graph(n);
//do something else, dont worry about that
}
Or allocate memory for array dynamically:
//C++
void PlotThis(unsigned int n)
{
Data_point* graph = new Data_point[n];
//do something else, dont worry about that
//Remember to free memory
delete graph;
}
//C
void plot_this(unsigned int n)
{
Data_point* graph = (Data_point*) malloc(sizeof(Data_point) * n);
//do something else, dont worry about that
//Remember to free memory
free(graph);
}