Link to home
Start Free TrialLog in
Avatar of drakkarnoir
drakkarnoir

asked on

Dynamic Pointers

Hello,

I have a class in which I wish to store a dynamic array of objects, such as:

class fruits
{
public:
string name;
};

class fruitType
{
public:
fruits *fruit;
int number_of_fruits; // stores the number i've already put in
}

Now, I figured from what I know about pointers, I could simply do:

void add_fruit(fruits new_fruit)
{
A = new fruits[4]; // 4 or whatever number_of_fruits is + 1
fruits[0].setValue("apples"); // errors here at run time, with cannot read memory

for(int i=0;i<4;i++)
// Here I want to copy each of the fruits[i]->name into A[i]->name but can't due to error above, which I suspect is the same reason it errors here

// Store the new array of objects A with the newly added new_fruit into fruitType->fruit
}

Any ideas?
Avatar of imladris
imladris
Flag of Canada image

HMmmm.

You pass in an argument of new_fruit, but it doesn't appear to get used anywhere.

fruits is a class name. Thus fruits[0] doesn't really mean anything.
You allocated an array of fruits to A (A=new fruits[4];). I suspect you meant A[0].setValue.

Though fruit doesn't appear to provide a setValue method......
Avatar of drakkarnoir
drakkarnoir

ASKER

I was giving a general idea of the setup, setValue is a function that sets "name" in fruits to the value passed.

new_fruit is the fruits type I wish to store into fruitType->fruit, as I have in my comment there. I did not add the code to it as I believe the problem is inherent with the memory read access error at run time.
"new_fruit is the fruits type I wish to store into fruitType->fruit"

Just realized that's not making what I meant to say clear,

new_fruit is the fruits type I wish to "append" to A (A being a copy of the existing fruitType->fruit but with 1 extra space for new_fruit) and then set A equal to fruitType->fruit.
To follow your code, this is what your function should look like:

void add_fruit(fruit fruit_obj)
{
A = new fruit[4]; // Allocate 4 objects of type fruit on the heap
for (int idx = 0; idx < 4; idx++)
{
     A[idx].SetName(fruit_obj->Name);
}
Sorry, the fruit_obj should be a ptr.
Function should look like add_fruit(fruit* fruit_Obj)
Also, get the name out of fruit_obj through some method.
Thanks mactep13 , that worked perfectly, except I don't think I made myself full clear on what I was trying to do, this is what I meant:

void fruitType::add_fruit(fruit *fruit_obj)
{
A = new fruit[4]; // Allocate 4 objects of type fruit on the heap
for (int idx = 0; idx < 4; idx++)
{
//     A[idx].SetName(fruit_obj->Name);
        A[idx].SetName(fruit[idx]->Name);  // read memory error
/// I want to loop through the fruit object array (fruitType->fruit and essentially copy it over to A, then I want to add/append the incoming fruit_obj to A and set A to fruitType->fruit
}
HMmm.

The "fruit" in "A[idx].SetName(fruit[idx]->Name);" still doesn't exist. It is a class, not an object.

I think we need to clarify the objective here. In the original question, given the mention of "dynamic pointer", and the method being named "add_fruit", it appears that you have a collection of fruit, that you wish to expand one by one.

However, your subsequent remarks appear to indicate that you have an array of fruit that you simply wish to copy to A.

I'm not clear on what you really intend. The former makes more sense, but the latter is what you are explicitly asking for.

To make the copy work you would, of course, have to be passing an array of fruit into the add_fruit method. Given that you could write the method as:

void fruitType::add_fruit(fruit *fruit_obj)
{   A=new fruit[4];
    for(int idx=0; idx<4; ++idx)
    {   A[idx].SetName(fruit_obj[idx].Name);
    }
    return;
}

Note again, that this requires that a pointer to an array of fruit objects be passed in to the add_fruit method.

Even with that, I am still not clear on where A is declared. Or how it is going to be accessed again. Or what the point of the fruitType class was.
Ok here is the problem for which I am trying to get this working:

I have to store user input (more than just fruit name) into an array.

Now, I also have to be able to "expand" that array on the fly. In other words, it has to be a dynamic array.

What I thought a good way to do it would be:

Make a class called "fruits" which stores the attributes about the fruits (user input).

Make a class called "fruitType" which manipulates an array of "fruits" objects. IE, addfruit, etc. It would store this array of "fruits" objects in a variable called "fruit_object_array" (I think fruitType->fruit was confusing, so let's use this now). So if I were to break it down:

User types in fruit attributes.

A new "fruits" object is created and passed into addfruit().

addfruit() then makes a new "fruits" (called A) object array, to accomodate the incoming fruit_obj.

Copy the class objects in fruitType "fruit_object_array" into "A".

Now that "A" has whatever "fruit_object_array" had but gives us room to add 1 more "fruits" object, I can set the last variable in "A" to the incoming fruit_obj.

Somehow (this part is the most confusing to me) set "A" to "fruit_object_array" in fruitType, so that "fruit_object_array" now has the old elements + the newly added fruit_obj.
"A" is really just a temporary variable that holds just one more element that "fruit_object_array" allowed for previously, so that a new "fruits" object can be added to it. Note, I have to use these two classes at the minimum.
I would suggest using a vector instead of the array. Vectors will resize automatically when you need more space. So do the following:

#include <vector>

std::vector<fruit> fruit_object_array;
Make him a global variable or make him alive for the scope of what you're doing.
Then, create
void add_fruit(fruit new_fruit_object)
{
       fruit_object_array.push_back(fruit_new_object);
}

If you want to access it, call at() function of the vector:

fruit fruit_to_get = fruit_object_array.at(index_of_vector_array);

That's all. Vector will take care of resizing the array for you.
You can dynamically create vector on the heap if you wish or dynamically create fruit objects on the heap as well.
vector<fruit*> fruit_array;
fruit* pFruit = new fruit;
fruit_array.push_back(pFruit);

If you have defined a destructor for the class, then you won't leak memory.

Hope this helps.
mactep
ASKER CERTIFIED SOLUTION
Avatar of mactep13
mactep13

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Don't forget to delete A.
delete [] A;
And what I meant for new_index is the new size of the array. Probably 1 more than what it used to be. Also, what I meant for fruit_array_object's size is the previous size - i.e. probably 1 less than the new size.
Still getting the cannot read access memory mactep13, here is fruit_array_object in my class fruitType:

fruits *fruit_array_object;

I unfortunately have to use arrays.

This line:

temp array of fruit_array_object *A = new fruit[new_index];

I made:

fruits *A = new fruit[new_index];

Is that okay?
Yes, that is fine. What about the rest?
I think it decides to bail out at this line right here:

A[idx] = fruit_array_object[idx];

The rest:

void fruitType::add_fruit(fruit fruit_object)
{
number_of_fruits++; // works as i expect it to
fruits *A = new fruit[number_of_fruits];
for (int idx = 0; idx < fruit_array_object's size; idx++)
{
     A[idx] = fruit_array_object[idx];
}
A[idx] = fruit_object;
fruit_array_object = A;
}

fruit_array_object is:

(public) fruits *fruit_array_object;

In fruitType
Yes, the index is higher than what you have in the fruit_array_object! Idx is set at one more! It points to last element of A as A has one more element than fruit_array_object. After you run the loop, A should have copies of fruit_array_object. That is what you did in
for (int idx = 0; idx < fruit_array_object's size; idx++)
{
     A[idx] = fruit_array_object[idx];
}
now, the A[idx] points to last member in A array. You may assign the new value of fruit_object there. But do not try to access fruit_array_object[idx] at this time as idx is one more than the size of the fruit_array_object!!!
After you assigned fruit_object to the last element of A, you may not assign the value of A (Which points to A[0]) to the fruit_array_object. As these array values are in a row, the new fruit_array_object will now actually use the new A values.
Don't forget to delete the old fruit_array_object BEFORE assigning A to it! But after the loop.

for (int idx = 0; idx < fruit_array_object's size; idx++)
{
     A[idx] = fruit_array_object[idx];
}
delete [] fruit_array_object;
fruit_array_objevc = A;

I got to run home. If you have questions, you'll have to wait for an hour or so.
mactep
Oh, and looking at you code above , in the loop, do this:
for (int idx = 0; idx <number_of_fruits-1 ; idx++)
{
     A[idx] = fruit_array_object[idx];
}
This is VERY important as you do not want to go higher than the elements of the previous array. But I think I already mentioned it so forgive me if I am going in circles. Does that make sense?
Doh! It was because the 0 index wasn't always defined, so I was attempting to write/access it! Hehe...it works perfectly, thank you much.