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 constructor. Again, if you add the copy assignment constructor, 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/