Problem with delete function.

So our prof tasked us to delete a block of array.
Technically in this case, to delete GroceryList_fin[0] or the first block in the GroceryList_fin array.

Our prof also said that we don't need to turn it into a vector or do some weird modifications in our code and said we only need to use the "delete" command, But it doesn't seem to be working for my code. Any suggestion(s)?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#include <iostream>
#include <string.h>

const size_t j=2;
const size_t k=4;
int GoodSum, QuantitySum;
std::string fruitNameList[j] = {"Apple", "Banana"}, vegNameList[j] = {"Broccoli", "Lettuce"};
int priceFruitList[j] = {10, 10},quantityFruitList[j] = {7, 8}, priceVegList[j]= {60, 50}, quantityVegList[j]= {12, 10};


class Fruit
{
    public:

        std::string fruitName;
        int fruitPrice;
        int fruitQuantity;

        //Constructor
        Fruit(std::string newFruitName = "", int newFruitPrice = 0, int newFruitQuantity = 0)
        {
            fruitName = std::move(newFruitName);
            fruitPrice = newFruitPrice;
            fruitQuantity = newFruitQuantity;
            //std::cout << "Constructor Called." << std:: endl; // To check if its working
        }

        //Deconstructor
        ~Fruit ()
        {
            //std::cout << "Destructor Called." << std::endl; // To check if its working
        }

        //Copy Constructor
        Fruit (const Fruit &copyFruit)
        {
            //std::cout << "Copy Constructor Called." << std::endl; // To check if its working
            fruitName = copyFruit.fruitName;
            fruitPrice = copyFruit.fruitPrice;
            fruitQuantity = copyFruit.fruitQuantity;
        }

        //Copy Assignment Operator
        Fruit &operator = (const Fruit &copy)
        {
            //std::cout << "Copy Assignment Operator was called." << std::endl;
            return *this;
        }

        //Display Attributes
        void printFruitDetails ()
        {
            if (fruitName.size()>=8)
            {
                std::cout <<"\t"<< this->fruitName << "\t " << this->fruitPrice << "\t " << this->fruitQuantity << std::endl;
            }
            else
            {
                 std::cout <<"\t"<< this->fruitName << "\t\t " << this->fruitPrice << "\t " << this->fruitQuantity << std::endl;
            }
        }
};

class Vegetable
{
    public:

        std::string vegName;
        int vegPrice;
        int vegQuantity;

        //Constructor
        Vegetable (std::string newVegName = "Broccoli", int newVegPrice = 60, int newVegQuantity = 12)
        {
            vegName = std::move(newVegName);
            vegPrice = newVegPrice;
            vegQuantity = newVegQuantity;
            //std::cout<< "Constructor Called." << std::endl; // To check if its working
        }

        //Deconstructor
        ~Vegetable ()
        {
            //std::cout << "Destructor Called." << std::endl; // To check if its working
        }

        //Copy Constructor
        Vegetable (const Vegetable &copyVegetable)
        {
            //std::cout << "Copy Constructor Called." << std::endl;
            vegName = copyVegetable.vegName;
            vegPrice = copyVegetable.vegPrice;
            vegQuantity = copyVegetable.vegQuantity;
        }

        // Copy Assignment Operator
        Vegetable &operator = (const Vegetable &copy)
        {
            //std::cout << "Copy Assignment Operator was called." << std::endl;
            return *this;
        }


        //Display Attributes
        void printVegDetails()
        {
            if (vegName.size()>=8)
            {
                std::cout <<"\t"<< this->vegName << "\t " << this->vegPrice << "\t\t " << this->vegQuantity << std::endl;
            }
            else
            {
                std::cout <<"\t"<< this->vegName << "\t\t " << this->vegPrice << "\t " << this->vegQuantity << std::endl;
            }
        }


};

class Grocery : public Vegetable, public Fruit
{
    public:
        std::string GoodName;
        int GoodPrice, GoodQuantity;

        Grocery (std::string GoodNamey="", int GoodPricey=0, int GoodQuantityy=0)
        {
            GoodName=std::move(GoodNamey);
            GoodPrice=GoodPricey;
            GoodQuantity=GoodQuantityy;
        }
        ~Grocery(){};

        Grocery (const Grocery &copyGood)
        {
            GoodName = copyGood.GoodName;
            GoodPrice = copyGood.GoodPrice;
            GoodQuantity = copyGood.GoodQuantity;
        }

        void printGroceryDetails()
        {
            if (GoodName.size()>=8)
            {
                std::cout <<"\t"<< this->GoodName << "\t " << this->GoodPrice << "\t\t " << this->GoodQuantity << std::endl;
            }
            else
            {
                std::cout <<"\t"<< this->GoodName << "\t\t " << this->GoodPrice << "\t\t " << this->GoodQuantity << std::endl;
            }
        }
};

Fruit *fruitlist_fin[j];
Vegetable *veglist_fin[j];
// Function to sum
void TotalSum(int x, int y);
void StoreData(int i);


int main ()
{
	// driver program


	std::cout <<"\t"<< "Good(s)" << "\t\t " << "Price(php)" << "\t " << "Quantity" << std::endl;

    for(int i =0; i < j; i++) //Store to Fruit and vegetable List
    {
        StoreData(i);
    }

    Grocery *GroceryList_fin[k];
    for(int i = 0; i < 2; i++)
    {
        GroceryList_fin[i]=new Grocery (veglist_fin[i]->vegName,veglist_fin[i]->vegPrice, veglist_fin[i]->vegQuantity);
        GroceryList_fin[i+2]=new Grocery (fruitlist_fin[i]->fruitName,fruitlist_fin[i]->fruitPrice, fruitlist_fin[i]->fruitQuantity);
    }

    for(int i = 0; i < k; i++)
    {
        GroceryList_fin[i]->printGroceryDetails();
        TotalSum(GroceryList_fin[i]->GoodPrice,GroceryList_fin[i]->GoodQuantity);
    }
    std::cout<<"\n\tTotal:\t\t "<<GoodSum<<"\t\t "<<QuantitySum<<"\n\n";


	delete[] GroceryList_fin;
	//GroceryList_fin[0] = NULL;

    for(int i = 0; i < k; i++)
    {
        GroceryList_fin[i]->printGroceryDetails();
    }
    std::cout<<"\n\tTotal:\t\t "<<GoodSum<<"\t\t "<<QuantitySum<<"\n\n";
}

void TotalSum(int x, int y) {
    GoodSum=GoodSum+(x*y);
    QuantitySum=QuantitySum+y;

}
void StoreData(int i) {
    fruitlist_fin[i] = new Fruit (fruitNameList[i], priceFruitList[i], quantityFruitList[i]);
    veglist_fin[i] = new Vegetable (vegNameList[i], priceVegList[i], quantityVegList[i]);
}
Grocery *GroceryList_fin[k];

delete[] GroceryList_fin;


GroceryList_fin IS NOT A POINTER. IT IS AN ARRAY THAT HAPPENS TO HOLD POINTERS.
This is a very, very critical distinction. You cannot delete arrays, as you did not allocate them. You can only delete something if you new it.

so GroceryList_fin[0] IS a pointer that you used NEW with and therefore you CAN delete it. The individual element, that one pointer, yes.
the outer array, however is again, NOT a pointer. GroceryList_fin itself.

Do you understand this?
A C style array is of the syntax
type name[constant size];
int     x      [100];
^^type  ^^name  ^^^ size
foo*   fp      [42] ///exactly the same as above. foo* is the type of the array. 
Last edited on
L188. No. You need to iterate over GroceryList_fin and delete each entry.

Also note that once you're done this, then L193 is invalid and you're then using a deleted item which is a non-no!

The code to delete each element of GroceryList_fin should be after L195.

You also need to do the same delete code for fruitlist_fin and veglist_fin.
As a side note, please keep to one thread for this problem. Even if you have a new question, its easier to follow than scattering new threads about.

You seem to be struggling with what pointers are and how they work. Do you understand the basics? The task you are trying to do is not that complicated, but if you do not understand the basics of what pointers are and how they work, it will still be extremely difficult to proceed. Do you need some help with it, or to take a moment to review it all? Pointers are often a challenging concept, and if poorly presented in your book or classroom, can become a major stumbling block for a while.
Last edited on
perhaps this on-line resource may help:

https://www.learncpp.com/cpp-tutorial/introduction-to-pointers/

PS. As has been said before, don't use:

 
#include <string.h> 


For C++ it's:

 
#include <string> 


<string.h> is for the c-string functions - when if needed you should use <cstring> in C++ code.

std::string for a type in this code is valid only because for your compiler <iostream> is also including <string> - but you shouldn't reply on this but include the #include's needed for the code.
Last edited on
<string.h> is the C library include for the C string functions.
https://cplusplus.com/reference/cstring/

In C++ code that C library header should be written as <cstring>.
So our prof tasked us to delete a block of array.

Our prof also said that we don't need to turn it into a vector or do some weird modifications in our code and said we only need to use the "delete" command,

1
2
3
4
5
6
7
8
9
Grocery* GroceryList_fin[k];
// initialize elements of array

// delete "a block", "simply" with delete

for(int i = 0; i < k; i++)
{
    GroceryList_fin[i]->printGroceryDetails();
}

Lets say that "a block" is just the first element and we merely delete the object that the pointer in the first element does point to.

Q: What will happen on line 8, when i==0?
A: We will dereference an invalid pointer. Undefined behaviour like crash, world peace, ananas in pizza, etc.

A good habit is to assign nullptr to pointer when it does not point to valid object, so one can see with a test that they are invalid.

That alone will not save the line 8, because that does dereference a pointer without a test.


A "no other modifications are necessary" would be true, if you would not use pointers after the point of deletion. You do use them, so modifications in that code are necessary. (There is nothing "weird" in that.)
1
2
3
4
5
6
7
8
9
if ( 0 < k ) {
  delete GroceryList_fin[0];
  GroceryList_fin[0] = nullptr;
}

for (int i = 0; i < k; i++)
{
    if ( GroceryList_fin[i] ) GroceryList_fin[i]->printGroceryDetails();
}
Your assignment operator doesn't assign.

You probably should remove your copy constructors/assignment operators, as the generated defaults will do the right thing, where you haven't.

EDIT: The destructors too. Simplify your code.
Last edited on
Topic archived. No new replies allowed.