Dynamically allocating an array of pointers to objects - c++

Question:
I have a class called croba.
In my console application I have a menu in which I can choose different options. After I choose an option, a switch statement checks my input and executes the block I chose.
In one of the cases I want the program to dynamicly alocate an array of pointers to class objects of a unknown size (the user is asked to input the size of the array), the catch is that the user input and the array must be alocated in the "case" block, but the alocated array has to be accessed globally later in the code. I declared a pointer to object globally like this:
croba *arrayOfObjectsPtr = NULL;
And here is the "case" block:
case 3:{
int numberOfElements;
int indexNumber;
if(!arrayOfObjectsPtr){
do{
cout << endl << "How many linked lists? "; cin >> numberOfElements;
}while(numberOfElements < 1);
croba *arrayOfObjectsPtrLocal[numberOfElements];
for (int i = 0; i < numberOfElements; i++){
arrayOfObjectsPtrLocal[i] = new croba;
}
}else{
cout << endl << "The array is already alocated!" << endl;
}
arrayOfObjectsPtr = arrayOfObjectsPtrLocal;
break;
}
I'm trying to figure out if there is a way to declare a pointer to an array of pointers to class objects globally and then alocating it later (because the number of elements is not known before).

In C++, the best practice is to use std::vector, which is the dynamic array class of the standard library. It is much nicer to use than C-style arrays. In your case it would look like this: std::vector<croba *> arrayOfObjectsPtr. Be careful though, because you will have to manually delete the pointers in the vector before destruction, like so:
for (auto& obj : arrayOfObjectsPtr)
delete obj;
If you don't want to perform the cleanup manually, like above, use a vector of smart pointers, like std::unique_ptr.
If you still want to use the old C-style array (which is not recommended), then declare it this way:croba** arrayOfObjectsPtr = new croba*[numberOfElements]. As for the cleanup, you'll have to do this:
for (int i = 0; i < numberOfElements; ++i)
delete arrayOfObjectsPtr[i];
delete[] arrayOfObjectsPtr;

Related

generate multidimensinal array instead of cout

I have this main function and i want to get an multidimensional array out of this to generate a graph instead of cout
int main(){
zoro z;
std:ifstream k("ggg.grf");
z.getfromstream(k);
for(int i =0 ; i < z.nnodes; i++){
edge_iteratore s = z.begin(i);
while(s != z.end(i)){
std:cout << "(" << (*s).height << "," << (*s).weight << ")" << std::endl;
++s;
}
}
return 0;
}
I' trying to get std::out to a function to generate a multidimensional array
so i have implemented this function to get an array,
int createarr(height,width){
int** ary = new int*[height];
for(int i = 0; i < height; ++i)
ary[i] = new int[weight];
}
but nothing works, how can i return an multidimensional array to use it in another function call instead of outputting it to the screen.
If height and weight are constexpr values you know at compile time, declare std::array<<std::array<int>, weight>, height>. This gets you locality of reference. If they are values you compute at runtime or that could vary, use vector<vector<int>>(height) and initialize each row. Then the compiler takes care of freeing the memory for you. If only one is fixed, you can also do a vector of arrays or an array of vectors.
It’s unfortunate that, because of the legacy char** argv interface of main(), every beginning C and C++ programmer thinks that’s how you do a two-dimensional array. A ragged array like that is almost never what you really want. But if you do, use std::vector to manage the memory for you.
The problem with your createarr() as written is that it doesn’t return any array pointer, but RAII is more likely what you want. And if you do have a sparse matrix that would benefit from raggedness, you can use a format like Compressed Sparse Row.
You need to return a pointer to the created array.
But you'll need to somehow deal with the fact that this is dynamically allocated memory, ie, you need to release it when you're done.
And you'll need to somehow encapsulate the dimensions too, which then means it needs to be a struct.
When you finally get tired of dealing with memory leaks, and understand how pointers work, use std::vector like the other guy said.
In the meantime, don't try to implement complicated algorithms in C without understanding the basics first. Brush up hard on how pointers and arrays actually work, first.

Do I need to manually delete or manage this unique_ptr

Do I need to manage this array in any way or will the unique_ptr take care of it? I have read that if arry gets assigned a new value then it will no longer be managed. I am new to this don't understand it very well.
int main() {
int i = 0;
int maxSpaceSize = 10;
unique_ptr<int[]> arry (new int[maxSpaceSize]());
for (i = 0; i < maxSpaceSize; i++) {
arry[i] = i;
cout << arry[i];
cout << endl;
}
return 0;
}
My goal in this is to make and understand dynamic arrays with automatic garbage collection. At some point I would ask the user to define the size of the array and that would be assigned to maxSpaceSize.
Thanks for helpful input.
Do I need to manage this array in any way or will the unique_ptr take care of it?
The std::unique_ptr will take care. There's a specialization for raw array deleters to call delete [] pointee;
I have read that if arry gets assigned a new value then it will no longer be managed.
That's wrong information (emphasis mine).
The assignment operator overload of std::unique_ptr will delete the old pointee, and further take care of the new one.
So whenever you write something like
maxSpaceSize = 50;
arry = unique_ptr<int[]>(new int[maxSpaceSize]);
that behavior will apply.
See Live Demo

Resizing an array of objects

i'm trying to do a homework in c++ where I can't use STD container classes such as vector,map,etc. Suppose we have the following archive:
2
El juego de Ender-Orson Scott-Tor Books-980.275.246-1985-6000
890365.2
2
The following-Lily Tyler-Tor Books-980.275.246-1985-6000
890365.2
For explanation purposes lets assume the number 2 means that a book is from X category, in this case 2 means is a fiction book, the next line after 2 is just the basic book data (name,author,publishing house,isbn,year,price) and the next line after that is just something that we are going to call CCF that is just another code for these types of books from the fiction category.
I'm just stuck on the next following part, I do know how to create an array of objects without container classes, but I do not know how to resize this array, i've been hearing about realloc, but i don't know how to use it with object array types. Libro is the parent of Ficcion and i'm trying to store Ficcion types in a polymorphic array of Libro because later on I have to introduce more classes in the same array, but for learning purposes i'm trying to resize with just the ficcion class, that being said, I do know the next following code is wrong because i'm using malloc and allocating the child object with new and then reallocating, but as I said I don't really get how to do this at all cause if you see the code you can tell that a new child object is created every 3 times inFile has executed getline, if you think something's missing please let me know, but I think what i've exposed covers the main issues of this question. I'm just asking for some enlightment of information when you have to deal with these types of arrays and you need to resize them, and I also know this would be way more easier with the container class but I can't use it this time. Thanks in advance! have a great day/night!
void BookManager::dataLoading(char* fileName){
//Arbitrary size to be resized later on (this is the array declared as **libro in the .h file)
libros = (Libro**)malloc(1 * sizeof(Libro**));
//file-in variable
std::ifstream inFile(fileName);
char type[10];
//counter
int i = 0;
//First getline
while (inFile.getline(type,sizeof(inFile)) && i < 2){
//Book Info; Second Getline
char bookInfo[100];
inFile.getline(bookInfo, sizeof(inFile));
//Additional book information; Third getline
char additional[60];
inFile.getline(additional, sizeof(inFile));
//Child creation
if (type[0] == '2'){
this->separateData(bookInfo);
//Ficcion constructor creating an object to store in the libros polymorphic array
libros[i] = new Ficcion(this->bookData[0], this->bookData[1], this->bookData[2], atof(this->bookData[3]), atoi(this->bookData[4]), atoi(this->bookData[5]), atof(additional));
}
i++;
//Failed reallocating
libros = (Libro**)realloc(libros, i+1 * sizeof(Libro**));
}
// This one is just testing if the array worked but i get an unhandled exception when i=1;
for (int i = 0; i < 2; i++){
std::cout << libros[i]->getTitulo() << '\n';
}
inFile.close();
}
UPDATE solution:
Since this is an array of pointers, as suggested down below i created a function where it resizes it and deletes the old one, returning the new one with the old data and a free space to store. So far this is working, thanks a lot guys!
Libro** BookManager::resize(Libro** arr,int size){
Libro** resized = new Libro*[size];
for (int i = 0; i < size-1; i++){
resized[i] = arr[i];
}
delete[]arr;
return resized;
}
malloc, realloc, etc.. are C library functions. Your question carries the C++ tag, not C.
In C++, objects are allocated with new, and deallocated with delete. This includes arrays.
To resize an existing array, you use new to allocate a new array, with the new size, copy into it the elements in the existing array, then deallocate the old array with delete.
(This is not 100% technically true, but this is likely what you are expected to do as part of your assignment).

Constant for a multi-dimensional array

I'm trying to create a multi-dimensional array, the size of which the user will supply.
So far I have this:
int definedgroups; // for number of groups needed
cout << "Enter the Number of Groups you require: " << endl;
cin >> definedgroups;
const int definedgroups = definedgroups;
int User_Groups [definedgroups] [4];
I believe the array needs constant values, so i tried assigning my variable as a constant but still no luck.
In C++, static arrays, that is, those defined like this:
foo arrayStatic[bar];
require bar to be a constant integer. In other words, the programmer needs to know its value beforehand.
Whenever bar is unknown, a dynamic array could be used instead. They're defined like this:
foo* arrayDynamic;
arrayDynamic = new foo[bar];
Here, bar could be an integer variable.
Don't forget that dynamic memory must be deallocated eventually. So, in this case, we can deallocate arrayDynamic like this:
delete [] arrayDynamic;
A two-dimensional dynamic array is defined analogously:
foo** arrayDynamic2D;
arrayDynamic2D = new foo*[bar];
for (int i = 0; i < bar; i++)
arrayDynamic2D[i] = new foo[baz];
and deallocated in a similar fashion:
for (int i = 0; i < bar; i++)
delete [] arrayDynamic2D[i];
delete [] arrayDynamic2D;
Static memory is allocated in the stack whereas dynamic memory is allocated in the heap.
It's not possible to do it in C++ using static arrays. Use std::vector in a hierarchical way (i.e. vectors of vectors) to implement a multi-dimensional array easily (though not necessarily very efficiently).
E.g.
std::vector<std::vector<double> > array(nrows, std::vector<double>(ncols));
creates a nrows x ncols matrix.
You need dynamic memory allocation using new:
int **User_Groups = new int*[definedgroups];
//Allocate memory for 2nd dimension
for (int i = 0; i < 4; ++i)
User_Groups[i] = new int[4];

How to manage an array of pointers to objects?

I have a problem with an array of pointers to objects :(..
I need to generate a dynamic vector of object and then return it in
order to manipulate it in another class. In the code below there is
Event class that is abstract and CarArrival that inherits from it and
can be instantiated.
Inside the class that generate and fill the array I have this function:
Event** EventGenerator::getEvents() {
Event* cars[EVENTS];
for (int i=0; i<EVENTS; i++) {
cars[i] = new CarArrival(generator->getNextNumber(8,(float)sqrt(0.4)));
}
sort(cars, cars+(EVENTS), Event::cmp);
return cars;
}
I invoke this function in onther class in this way:
Event** cars = generator->getEvents();
for(int i=0; i<EVENTS; i++) {
cout << i <<":" << (*cars)[i]->getScheduleTime() << endl;
}
after the print of the first element i get "Segmentation Fault".
I have read some things online and I understand that I mistake since (*cars) evaluates to a
pointer to the first element of the array, in fact I can print the first element and not the other, but I cannot figure out how to access every element of the array in the second class.
How can I face this?
Thanks to all,
Alberto
I'd suggest that you use a std::vector<Event*> instead. You'll save a lot of pain this way. It takes care of all the nasty memory management in the background, and you can easily push any number of items into it. The best part in your case is, that you can simply return a vector which is not safe with a normal array.
Also your Event* cars[EVENTS]; is declared locally in you function. After you have finished it, it ceases to exist, which might cause your Segfault. You'd have to dynamically allocate the array with new, but still, try it with std::vector, see the documentation here.
EDIT: Sample Usage:
std::vector<Event*> EventGenerator::getEvents() {
std::vector<Event*> cars;
for (int i=0; i<EVENTS; i++) {
cars.push_back(new CarArrival(generator->getNextNumber(8,(float)sqrt(0.4))));
}
sort(cars.begin(), cars.end(), Event::cmp);
return cars;
}
std::vector<Event*> cars = generator->getEvents();
for(int i=0; i<cars.size(); i++) {
cout << i <<":" << (*cars)[i]->getScheduleTime() << endl;
}
I believe the cleanest way to handle a dynamic vector of pointers to dynamically allocated objects is to use a boost::ptr_vector. It handles everything you need, including allocation of the space to store the pointers, and deletion of those pointers afterwards.
Wouldn't be better to return vector<Event*> or vector<shared_ptr<Event>> instead of raw pointers? This way you would gain:
Automation of the memory management
Dynamic array with built-in length instead of fixed one
As mentionned by Constantinuis, you are returning the value of a pointer to a memory location that is only valid in the scope of the getEvents() function (it's allocated on the stack). You're bound to get a segfault next time.
You probably want to allocate the memory for this array in the heap (using 'new' if my C++'s isn't too rusty), and then you'll have to deal with freeing the memory later.
http://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter13.html