Creation of Dynamic Array of Dynamic Objects in C++ - c++

I know how to create a array of dynamic objects.
For example, the class name is Stock.
Stock *stockArray[4];
for(int i = 0 ; i < 4;i++)
{
stockArray[i] = new Stock();
}
How do you change this to dynamic array of dynamic objects?
What I tried:
Stock stockArrayPointer = new Stock stock[4];
It doesn't work and the error is "The value of Stock** cannot be used to initalize an entity of type Stock.
Second question is after the creation of dynamic array of dynamic objects, what is the syntax to access the pointers in the array.
Now, I use stockArray[i] = new Stock(); How will this change?
Need some guidance on this...

If you are using c++ then you shouldn't reinvent the wheel, just use vectors:
#include <vector>
std::vector< std::vector< Stock > > StockVector;
// do this as many times as you wish
StockVector.push_back( std::vector< Stock >() );
// Now you are adding a stock to the i-th stockarray
StockVector[i].push_back( Stock() );
Edit:
I didn't understand your question, if you just want to have and array of arrays allocated on the heap just use:
Stock** StockArrayArray = new Stock*[n]; // where n is number of arrays to create
for( int i = 0; i < n; ++i )
{
StockArrayArray[i] = new Stock[25];
}
// for freeing
for( int i = 0; i < n; ++i )
{
delete[] StockArrayArray[i];
}
delete[] StockArrayArray;

The type of a variable to a dynamic array is a pointer to the first object of the array. You want an array of dynamically allocated Stock objects, so an array of pointers to Stock, so your variable is a pointer to a pointer to Stock:
int n = 4; // dynamic size of the array;
Stock** stockArray = new Stock*[n];
for (int i = 0; i != n; ++i)
{
stockArray[i] = new Stock();
}
and freeing it:
for (int i = 0; i != n; ++i)
{
delete stockArray[i];
}
delete[] stockArray;

Stock* stockArrayPointer = new Stock [4];
works only if the Stock class has a zero argument constructor
if it does not have any zero argument constructor you cannot create an array of dynamic objects dynamically
you can as said create a array of dynamic object with a static array like
Stock stockArrayPointer[4]={Stock(args),Stock (args)};
but the syntax
Stock* stockArrayPointer=new Stock[4]{Stock(args),Stock (args)}; does not hold
or as said
use vectors...
vectors are memory allocated on heap
so the vector is a dynamic allocation
vector<Stock> V;
V.push_back(Stock(args));
or
V.push_back(new Stock(args));
The reason why
Stock* stockArrayPointer=new Stock[4]{Stock(args),Stock (args)};
does not hold
is because
this means
you are using the new operator incorrectly

I did something which worked perfectly:
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
class student {
string name;
int age;
int roll;
public:
student() {
name="";
age=0;
roll=0;
}
student (string n, int a, int r) {
name=n;
age=a;
roll=r;
}
void show_details ();
};
void student::show_details() {
cout << "Name: " << name << "\n";
cout << "Age: " << age << "\n";
cout << "Roll No: " << roll << "\n";
}
int main() {
string a; int b, c, n;
cin >> n;
student **obj;
obj=(student**)malloc(n*sizeof(student*));
for (int i=0; i<n; i++) {
cin >> a;
cin >> b;
cin >> c;
obj[i]=new student(a,b,c);
}
for (int i=0; i<n; i++) {
obj[i]->show_details();
}
for (int i=0; i<n; i++) free (obj[i]);
free (obj);
}
Yes... I used pointer to pointer for the array part, and it worked perfectly for variable sized arrays.

Related

Calling a Function in a Class with Parameters C++

I'm practicing in order to better understand dynamic arrays and using them in a class. However, I'm struggling to call my functions inside the class. I have no issue with my int size variable, but my int myArray variable is giving me problems. I get the error "expected a member name" when I try to call my void functions in my main function. Are arrays not allowed to be used in this situation?
#include <iostream>
using namespace std;
class myClass
{
public:
int size;
int* myArray = new int[size];
void storeData(int& size, int (&myArray)[]);
void printData(int& size, int(&myArray)[]);
};
void myClass::storeData(int& size, int(&myArray)[])
// Stores array data.
{
cout << "Enter Size of the array: ";
cin >> size;
// User determines array size.
for (int x = 0; x < size; x++)
{
cout << "Array[" << x << "]: ";
cin >> myArray[x];
// User determines array values.
cout << endl;
}
}
void myClass::printData(int &size, int(&myArray)[])
// Displays values of the array.
{
cout << "Value of the arrays are: ";
for (int x = 0; x < size; x++)
{
cout << myArray[x] << " ";;
}
delete[]myArray;
}
int main()
{
myClass object;
object.storeData(object.size, object.(&myArray)[]);
// E0133 expected a member name.
object.printData(object.size, object.(&myArray)[]);
// E0133 expected a member name.
}
There are a couple issues here, I will try to address all of them.
When passing an array to a function, never use [] syntax. In C and C++, arrays decay to pointers, so we do not need [] nor &.
This is valid syntax to pass an array:
int my_array [] = {1,2,3,4};
my_function(my_array, 4);
...
void my_function(int * array, size_t size)
{
//Iterate over the array or do something...
}
In addition, if a function exists within a class, it can access class members freely, meaning we do not have to pass them in at all. See the following change to your code:
void myClass::storeData(int size)
// Stores array data. We do NOT need a pointer to the object array, we already have it!
{
cout << "Enter Size of the array: ";
cin >> size;
// User determines array size.
for (int x = 0; x < size; x++)
{
cout << "Array[" << x << "]: ";
cin >> myArray[x];
// User determines array values.
cout << endl;
}
}
Lastly, dynamic sized arrays must be allocated dynamically. Do not use int* myArray = new int[size]; in your class definition, because size is not yet initialized. Instead, use a constructor or use your store_data function to allocate the memory.
class myClass
{
public:
size_t size;
int * myArray; //Do not allocate anything here...
myClass(size_t size)
{
this->size = size;
myArray = new int[size];
}
};
You can get the size however you want, via user input, etc. and pass this to the constructor or an allocator function like storeData.

C++ Dynamic data – how to obtain it and how to get rid of it

The code below – it's a skeleton of a program operating on the dynamic collection of data. The idea is to use a structure containing two fields: the first stores the number of elements in collections, and the second is the actual collection (a dynamically allocated vector of ints). As you can see, the collection is filled with the required amount of pseudo-random data.
Unfortunately, the program requires completion, as the most important function.
Here's what i expect from the function:
if the collection is empty, it should allocate a one-element vector and store a new value in it.
if the collection is not empty, it should allocate a new vector with a length greater by one than the current vector, then copy all elements from the old vector to the new one, append a new value to the new vector and finally free up the old vector.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
struct Collection {
int elno;
int *elements;
};
void AddToCollection(Collection &col, int element) {
//the first part of the funtion
if (col.elno==0){
col.elements= new int[1];
col.elements[0]= element;
}
//this is the second part but i do not know how to do it.
//Please help me to complete***************
else {
int *temp;
temp = new[];
}
}
void PrintCollection(Collection col) {
cout << "[ ";
for(int i = 0; i < col.elno; i++)
cout << col.elements[i] << " ";
cout << "]" << endl;
}
int main(void) {
Collection collection = { 0, NULL };
int elems;
cout << "How many elements? ";
cin >> elems;
srand(time(NULL));
for(int i = 0; i < elems; i++)
AddToCollection(collection, rand() % 100 + 1);
PrintCollection(collection);
delete[] collection.elements;
return 0;
}
vector container is originally dynamic container. so u can use vector.
Just declare vector variable in structure and use it in AddToCollection function.
struct Collection {
int elno;
std::vector<int> elements;
};
void AddToCollection(Collection &col, int element) {
col.elements.push_back(element);
col.elno++;
}
like this.
Here is what you are looking for:
void AddToCollection(Collection &col, int element)
{
if(col.elements == NULL)
{
col.elements = new int[1];
col.elements[0] = element;
col.elno = 1;
}
else
{
int *newArr = new int[col.elno+1];
for(int i = 0; i < col.elno; i++)
{
newArr[i] = col.elements[i];
}
newArr[col.elno] = element;
delete[] col.elements;
col.elements = new int[col.elno+1];
for(int i = 0; i < col.elno+1; i++)
{
col.elements[i] = newArr[i];
}
delete[] newArr;
newArr = NULL; // avoid dangling pointer
col.elno++;
}
}
For sure using vector container is a great ideea but the exercise require no modification to the main function. The objective of this exercise is to help the student to understand dynamically allocated memory.

How to pass Dynamic Array by reference C++

I'm having trouble understanding how to pass a dynamic array by reference in C++.
I've recreated the problem in this small isolated code sample:
#include <iostream>
using namespace std;
void defineArray(int*);
int main()
{
int * myArray;
defineArray(myArray);
/** CAUSES SEG FAULT*/
//cout<<(*(myArray)); //desired output is 0
return 0;
}
void defineArray(int*myArray)
{
int sizeOfArray;
cout<<"How big do you want your array:";
cin>>sizeOfArray;
/** Dynamically allocate array with user-specified size*/
myArray=new int [sizeOfArray];
/** Define Values for our array*/
for(int i = 0; i < sizeOfArray; i++)
{
(*(myArray+i))=i;
cout<<(*(myArray+i));
}
}
myArray is passed by value itself, any modification on myArray (such as myArray=new int [sizeOfArray];) has nothing to do with the original variable, myArray in main() is still dangled.
To make it passed by reference, change
void defineArray(int*myArray)
to
void defineArray(int*& myArray)
This solution is hopelessly complicated. You don't need new[], pointers or even a reference parameter. In C++, the concept of "dynamic arrays" is best represented by std::vector, which you can just just use as a return value:
#include <iostream>
#include <vector>
std::vector<int> defineArray();
int main()
{
auto myArray = defineArray();
if (!myArray.empty())
{
std::cout << myArray[0] << "\n";;
}
}
std::vector<int> defineArray()
{
int sizeOfArray;
std::cout << "How big do you want your array:";
std::cin >> sizeOfArray;
std::vector<int> myArray;
for (int i = 0; i < sizeOfArray; i++)
{
myArray.push_back(i);
std::cout<< myArray[i] << "\n";
}
return myArray;
}
push_back will work intelligently enough and not allocate new memory all the time. If this still concerns you, then you can call reserve before adding the elements.

Doubling of an arbitrary array of strings

1: My goal is to create two arbitrary arrays using pointers: one with names, another one with corresponding numbers. From my previous question, I know that doubling an array is a good way to deal with arbitrary sizes. So, I am trying to double both arrays correspondingly. But while the doubling of an int array goes well, array of strings does not double. Could you explain, what is the problem with that?
2: Is there an alternative to the creation of arbitrary array of strings to store list of names?
Here is the part of the code:
string *pn = new string [size];
int *pd = new int [size];
while (x != 0) {
if (size == k+1) {
pn = doubn (pn, size);
pd = doubd (pd, size);
}
pn[k] = name;
pd[k] = val;
cout << "Another entry? (0 for exit)";
cin >> x;
getline (cin, name, ',');
cin >> val;
++k;
}
for (int i = 0; i<k; ++i) {
cout << pn[i] << " - " << pd[i] << " days"; }
del (pn, pd, k);
cin.get ();
cin.ignore();
}
string* doubn (string *pn, int size) {
string* pnn = new string [size*2];
for (int i = 0; i < size; ++i) {
pnn [i] = pn[i]; }
delete pn;
return pnn; }
int* doubd (int *pd, int size) {
int *pdn = new int [size*2];
for (int i = 0; i<size; ++i) {
pdn [i] = pd[i];}
delete pd;
return pdn;}
To have arbitrary sized arrays, use vectors.
Vectors are a part of the C++ Standard Template Library (STL) and required the #include<vector> header.
For more information, check this out: http://www.cplusplus.com/reference/vector/vector/
Also, you should be using delete [] instead of delete.
You use delete on memory allocated by new[], you should use delete[] instead.
Using std::vector would be simpler and less error prone anyway.

creating multiple objects for classes/structures?

I have a question. Is it possible to create multiple objects during run time for classes or structures?
#include<iostream>
#include<conio.h>
using namespace std;
struct node
{
int no;
};
int main()
{
int i;
for(i=0;i<4;i++)
{
struct node s[i];
}
cout<<"Enter the values";
for(i=0;i<4;i++)
{
cin>>s[i].no;
}
cout<<"The values are:";
for(i=0;i<4;i++)
{
cout<<s[i].no<<endl;
}
getch();
return 0;
}
I tried the method above , but didn't succeed . Any help would be appreciated
replace
for(i=0;i<4;i++)
{
struct node s[i];
}
with
struct node s[4];
the way you wrote your program will not work. You defined the node array s inside a block so it will not be visible outside of that block.
If you want to dynamically allocate the memory you have to do something like:
struct node *s = new node[YourDesiredSize];
or if you like the c style (not recommended):
struct node *s;
s = (node*)malloc(YourDesiredSize * sizeof (node));
and don't forget to free the memory.
for(i=0;i<4;i++)
{
struct node s[i];
}
Here you create an array of nodes inside a for loop. This is local and only available in the for loop. In addition this will not compile as it is written because i is not a constant expression. Even however if you used the new operator to allocate the array as before it would only be available in the for loop.
Instead you should declare your array somewhere else :
node s[4];
This will create an array of size 4 by calling the default c'tor of node. Then your code should work.
If you want to create instances of structs or classes at runtime you need to use the new operator.
struct node* n = new n[4]; // creates an array of 4 node structs
for( int i=0; i<4; ++i )
{
n[i]->no = i;
}
Since this is dynamically allocated memory you are responsible for freeing it when the structs are no longer needed.
delete[] n; // free dynamically allocated memory - the brackets are needed because this an array
That can be done with a native array of instances (of structures or classes) if you know the count of them, or you can used collections such as list or vector if you don't.
#include<iostream>
#include<list>
using namespace std;
struct node
{
int no;
node() { }
node(int i) { no = i; }
};
int main()
{
struct node * arrayOf4Nodes = new node[4];
cout << "Enter four values: ";
int i;
for(i = 0; i < 4; i ++) {
cin >> arrayOf4Nodes[i].no;
}
cout << "The values are:" << endl;
for(i = 0; i < 4; i ++) {
cout << arrayOf4Nodes[i].no << endl;
}
delete [] arrayOf4Nodes;
// OR for unknown lengths
cout << "Enter values ending with -1000 to exit: ";
list<node> listOfNodes;
while (true) {
cin >> i;
if (cin.eof() || i == -1000)
break;
listOfNodes.push_back(node(i));
}
cout << "The values are:" << endl;
for (node n : listOfNodes) {
cout << n.no << endl;
}
return 0;
}