initializing arrays of vectors on the heap, c++ - c++

My goal is to create an array of vectors (with a capacity of 10 integers for each vector) on the heap. I can create my array easily enough:
vector<int>* test = new vector<int>[NUM_VERTS];
However, this creates an array of empty vectors. I know each vector will store at least 10 ints and so I want to create the vectors with size 10 to start with to avoid having them re-size themselves multiple times (I'm reading in a big file and so efficiency is important). How can I modify the statement above so that it does what I want?
As a side note, I'm using VS 2013 and struggling with its debugger. When I run the debugger and look at the contents of test above, it shows me the memory address of the area it points to but not the contents stored at the address. Does anyone know how I can view the contents instead of the address?
Thanks
PS I'm creating the array of vectors on the heap instead of the stack because the array is extremely large (just under a million entries). When I tried to create it on the stack I got a stack overflow error.

You can create a vector of vectors that is not the same as an array but for your use case it should be equivalent:
std::vector< std::vector<int> > test(NUM_VERTS, std::vector<int>(10));
there's no need to allocate it with new because vector elements are already on the heap.
If you need the pointer to the first contained vector you can just use
std::vector<int> *p = &test[0];
and use p as if it was an heap-allocated array of vectors (all the elements of a vector are guaranteed to be consecutive in memory).

Related

Dynamic and static array

I am studying C++ reading Stroustrup's book that in my opinion is not very clear in this topic (arrays). From what I have understood C++ has (like Delphi) two kind of arrays:
Static arrays that are declared like
int test[3] = {10,487,-22};
Dynamic arrays that are called vectors
std::vector<int> a;
a.push_back(10);
a.push_back(487);
a.push_back(-22);
I have already seen answers about this (and there were tons of lines and concepts inside) but they didn't clarify me the concept.
From what I have understood vectors consume more memory but they can change their size (dynamically, in fact). Arrays instead have a fixed size that is given at compile time.
In the chapter Stroustrup said that vectors are safe while arrays aren't, whithout explaining the reason. I trust him indeed, but why? Is the reason safety related to the location of the memory? (heap/stack)
I would like to know why I am using vectors if they are safe.
The reason arrays are unsafe is because of memory leaks.
If you declare a dynamic array
int * arr = new int[size]
and you don't do delete [] arr, then the memory remains uncleared and this is known as a memory leak. It should be noted, ANY time you use the word new in C++, there must be a delete somewhere in there to free that memory. If you use malloc(), then free() should be used.
http://ptolemy.eecs.berkeley.edu/ptolemyclassic/almagest/docs/prog/html/ptlang.doc7.html
It is also very easy to go out of bounds in an array, for example inserting a value in an index larger than its size -1. With a vector, you can push_back() as many elements as you want and the vector will resize automatically. If you have an array of size 15 and you try to say arr[18] = x,
Then you will get a segmentation fault. The program will compile, but will crash when it reaches a statement that puts it out of the array bounds.
In general when you have large code, arrays are used infrequently. Vectors are objectively superior in almost every way, and so using arrays becomes sort of pointless.
EDIT: As Paul McKenzie pointed out in the comments, going out of array bounds does not guarantee a segmentation fault, but rather is undefined behavior and is up to the compiler to determine what happens
Let us take the case of reading numbers from a file.
We don't know how many numbers are in the file.
To declare an array to hold the numbers, we need to know the capacity or quantity, which is unknown. We could pick a number like 64. If the file has more than 64 numbers, we start overwriting the array. If the file has fewer than 64 (like 16), we are wasting memory (by not using 48 slots). What we need is to dynamically adjust the size of the container (array).
To dynamically adjust the capacity of an array, a new larger array must be created, then elements copied and the old array deleted.
The std::vector will adjust its capacity as necessary. It handles the dynamic allocation of memory for you.
Another aspect is the passing of the container to a function. With an array, you need to pass the array and the capacity. With std::vector, you only need to pass the vector. The vector object can be queried about its capacity.
One Security I can see is that you can't access something in vector which is not there.
What I meant by that is , if you push_back only 4 elements and you try to access index 7 , then it will throw back an error. But in array that doesn't happen.
In short, it stops you from accessing corrupt data.
edit :
programmer has to compare the index with vector.size() to throw an error. and it doesn't happne automatically. One has to do it by himself/herself.

assign space for vector of pointer to struct

For some reason, I have a vector of pointer of struct, I would like to assign new space to every block of the vector. But I don't want to do it in a loop for every block as it may slow the whole process. Is there a faster way to do it?
Could anyone provide me a solution with code?
This is what I current doing("pool" is the struct name):
vector<pool*> poolPointer(vectorSize);
for(int i = 0; i<poolPointer.size() ;i++){
poolPointer.at(i) = new pool;}
I think it is very slow thus I would like to search for a faster way to allocate space and return point of struct to each individual block in the vector.
I has nothing to do with vector. What you are looking for is custom memory allocation, and in place operator new in particular. So you can allocate a single chunk of memory for all your pool instances and then create instances in this memory chunk.
EDIT:
As #JSF commented, you can allocate many instances all together as an array of "values", not pointers. You can then use vector of pointers if you wish, or you can use vector of values and don't bother with pointers at all. I'd start with vector of values and only if profiling showed that frequent removal from a vector is a bottleneck I'd think about vector of pointers as an optimisation.

C++ implementation of an array of vectors

Background: I want to implement a 3-d collision detection algorithm and would like to fragment the search space into cubes so that I only check for collisions when objects are close enough.
Actual Question: I was thinking of using an array of vectors to store pointers to the objects I am going to iterate over. For example box[0][0][0] would be a vector holding pointers to the objects in one corner of the simulation space. Regardless of whether this is an optimal solution, I am wondering how c++ handles arrays of vectors. Would the array hold pointers to the vectors so that their subsequent re-allocation have no effect on the validity of the array, or would the vectors be created inside the array and then moved out, causing undefined behavior?
Similar questions did not have answers specific to this implementation detail. Sorry if this is actually answered elsewhere and I missed it.
An STL vector holds a pointer to a heap buffer that contains the actual data. This allows the vector to resize the buffer on demand without invalidating the vector object itself. (See documentation of vector)
So, to answer your question. An array of vectors will not become invalid if one of the vectors needs to be resized. An array of pointers to vectors would also not become invalid if one of the vectors needs to be resized.
In STL a vector is an implementation of a dynamic array ( an array that can be resided on the fly). This essentially means that the array is dynamically allocated, and the user gets a pointer to the array on the heap. When more space is needed, a new array is allocated (usually double of it's previous size), the contents of the old one is copied over and the old array freed. And that is how data consistency is handled.
Now, when you have a array of vectors, statically allocated like the question shows, you have in memory (stack, or .data section, depending where you declare this array) an or 3 vector objects, allocated one after the other in memory, each one will hold a pointer to the an array allocated on the heap.
I hope this answers your question.

How can I discover the size/length(in bytes) of a std::vector?

I have a vector and I want to write and read it to a file but it is not possible to determine the logical size of a vector using the sizeof operator.
So what shall I do?
A c++ std::vector has a method size() which returns its size.
EDIT: as I get it now you need to compute the memory a given vector uses. You can't use sizeof for that as a vector uses dynamic memory and stores only a pointer of a dynamic array containing its elements. So my best suggestion would be to multiply the memory each element requires by the number of elements. Note this again will not work if the objects stores a pointer to some dynamically allocated objects - you will have again to compute their sizes separately.
There is no easy way to compute the memory a vector size in bytes in c++ that I know of.

Dynamic memory allocation, C++

I need to write a function that can read a file, and add all of the unique words to a dynamically allocated array. I know how to create a dynamically allocated array if, for instance, you are asking for the number of entries in the array:
int value;
cin >> value;
int *number;
number = new int[value];
My problem is that I don't know ahead of time how many unique words are going to be in the file, so I can't initially just read the value or ask for it. Also, I need to make this work with arrays, and not vectors. Is there a way to do something similar to a push_back using a dynamically allocated array?
Right now, the only thing I can come up with is first to create an array that stores ALL of the words in the file (1000), then have it pass through it and find the number of unique words. Then use that value to create a dynamically allocated array which I would then pass through again to store all the unique words. Obviously, that solution sounds pretty overboard for something that should have a more effective solution.
Can someone point me in the right direction, as to whether or not there is a better way? I feel like this would be rather easy to do with vectors, so I think it's kind of silly to require it to be an array (unless there's some important thing that I need to learn about dynamically allocated arrays in this homework assignment).
EDIT: Here's another question. I know there are going to be 1000 words in the file, but I don't know how many unique words there will be. Here's an idea. I could create a 1000 element array, write all of the unique words into that array while keeping track of how many I've done. Once I've finished, I could provision a dynamically allocate a new array with that count, and then just copy the words from the initial array to the second. Not sure if that's the most efficient, but with us not being able to use vectors, I don't think efficiency is a huge concern in this assignment.
A vector really is a better fit for this than an array. Really.
But if you must use an array, you can at least make it behave like a vector :-).
Here's how: allocate the array with some capacity. Store the allocated capacity in a "capacity" variable. Each time you add to the array, increment a separate "length" variable. When you go to add something to the array and discover it's not big enough (length == capacity), allocate a second, longer array, then copy the original's contents to the new one, then finally deallocate the original.
This gives you the effect of being able to grow the array. If performance becomes a concern, grow it by more than one element at a time.
Congrats, after following these easy steps you have implemented a small subset of std::vector functionality atop an array!
As you have rightly pointed out this is trivial with a Vector.
However, given that you are limited to using an array, you will likely need to do one of the following:
Initialize the array with a suitably large size and live with poor memory utilization
Write your own code to dynamically increase the size of the array at run time (basically the internals of a Vector)
If you were permitted to do so, some sort of hash map or linked list would also be a good solution.
If I had to use an array, I'd just allocate one with some initial size, then keep doubling that size when I fill it to accommodate any new values that won't fit in an array with the previous sizes.
Since this question regards C++, memory allocation would be done with the new keyword. But what would be nice is if one could use the realloc() function, which resizes the memory and retains the values in the previously allocated memory. That way one wouldn't need to copy the new values from the old array to the new array. Although I'm not so sure realloc() would play well with memory allocated with new.
You can "resize" array like this (N is size of currentArray, T is type of its elements):
// create new array
T *newArray = new T[N * 2];
// Copy the data
for ( int i = 0; i < N; i++ )
newArray[i] = currentArray[i];
// Change the size to match
N *= 2;
// Destroy the old array
delete [] currentArray;
// set currentArray to newArray
currentArray = newArray;
Using this solution you have to copy the data. There might be a solution that does not require it.
But I think it would be more convenient for you to use std::vectors. You can just push_back into them and they will resize automatically for you.
You can cheat a bit:
use std::set to get all the unique words then copy the set into a dynamically allocated array (or preferably vector).
#include <iterator>
#include <set>
#include <iostream>
#include <string>
// Copy into a set
// this will make sure they are all unique
std::set<std::string> data;
std::copy(std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string>(),
std::inserter(data, data.end()));
// Copy the data into your array (or vector).
std::string* words = new std::string[data.size()];
std::copy(data.begin(), data.end(), &words[0]);
This could be going a bit overboard, but you could implement a linked list in C++... it would actually allow you to use a vector-like implementation without actually using vectors (which are actually the best solution).
The implementation is fairly easy: just a pointer to the next and previous nodes and storing the "head" node in a place you can easily access to. Then just looping through the list would let you check which words are already in, and which are not. You could even implement a counter, and count the number of times a word is repeated throughout the text.