Reputation: 327
I am a beginner in C++ and trying to solve a problem from an introductory C++ textbook. Please consider the following piece of code.
#include <iostream>
#include <cstring>
using namespace std;
class books
{
char *author;
char *title;
float price;
char *publisher;
int stockposition;
int reqmt;
float totalprice;
public:
books() {}
books (char *, char *, float, char *, int);
~books()
{
delete author;
delete title;
delete publisher;
cout << "Destructor invoked\n";
}
void display (void);
char * returnauthor(void) { return author;}
char * returntitle(void) { return title;}
};
.
.
.
books *B = new books [num];
for (i = 0; i < num; i++)
{
cout << "Enter the author, title, price, publisher and number of copies available for book no. " << i + 1 << endl;
cin >> author >> title >> price >> publisher >> stock;
B[i] = books (author, title, price, publisher, stock);
}
I thought since I am using char * pointers for strings in my class, I should use an explicit destructor which I defined above.
As you can see I have declared the array B[num] of objects of class books outside of the for()
statement. However, I find that the destructor is invoked within the for statement itself and the data recorded in the class is not available beyond the for()
.
Can you please point out the mistake here and what could I do so that the destructor is called only at the end of main()
?
Secondly, if, instead of an explicit destructor, I make a function like destroybooks()
below and call it through a for loop,
void destroybooks (void)
{
delete []author;
delete []title;
delete []publisher;
}
do I then also need to have a statement like delete []B;
at the very end?
Upvotes: -1
Views: 139
Reputation: 67
The answer is complex, dealing with multiple different kinds of constructors.
Let's break it down:
books *B = new books [num];
This actually calls the default constructor num
times. Try putting a cout
statement in the default constructor and you will see it being created.
B[i] = books (author, title, price, publisher, stock);
This is called Copy-Assignment operator. Again, if you add the copy assignment operator, book& operator=(const book& other)
and add a cout
, it will appear. Because you are assigning to a value that already exists, the old value is getting destructed (the value you instantiated when you create the original books
array) and being updated with the new value in the for loop.
what could I do so that the destructor is called only at the end of main()
There are ways to do this with C++ pointers, such as having an array of pointers. Something like this:
Foo** foo = new Foo*[num];
for (int i = 0; i < num; i++)
{
foo[i] = new Foo();
}
for (int i = 0; i < num; i++)
{
delete foo[i];
}
delete[] foo;
But this is rather complicated. There are many solutions, but I think the simplest solution in your case is just to update the instance rather than create a new object, i.e. B[i].author = author
Secondly, if, instead of an explicit destructor, I make a function like destroybooks() below and call it through a for loop, do I then also need to have a statement like delete []B; at the very end?
Yes. By calling, new
with books* b = new books[num];
you are adding data to the heap, which must explicitly released. Otherwise, the memory can be leaked. I would suggest looking up the new
keyword. Some resources below to get your started:
https://en.cppreference.com/w/cpp/language/new
https://www.geeksforgeeks.org/new-and-delete-operators-in-cpp-for-dynamic-memory/
Upvotes: -1