I recently ran into this problem at work. A library I'm using makes use of reference counted objects and implements its own way of handling it. Part of the implementation is that each class of the library has a private destructor. Im guessing this is to prevent creation of objects on the stack as the library manages objects lifetime automatically (Its a scene graph).
Anyways, I wanted to allocate an array of such a class on the heap and ran into the following problem:
#include <iostream>
using namespace std;
class test
{
public:
test() {
cout << "ctor" << endl;
}
//~test() = delete; also doesnt work
private:
~test()
{
cout << "dtor" << endl;
}
};
int main()
{
//works
auto oneInstance = new test;
//doesnt work
auto manyInstances = new test[3];
}
The array allocation produces the following error using GCC:
source_file.cpp: In function ‘int main()’:
source_file.cpp:15:5: error: ‘test::~test()’ is private
~test()
^
source_file.cpp:26:36: error: within this context
auto manyInstances = new test[3];
^
Why does the destructor need to be public/available in order to allocate an array of this class on the heap? It works fine when only allocating a single instance like in the line before. I also tried using the more modern "delete" syntax, but it produced the same result.
Is there any kind of magic in the new[] operator that I'm not aware of?
EDIT:
Thanks for the quick help. Im wondering why this code doesnt print "dtor" twice though:
#include <iostream>
using namespace std;
class test
{
public:
test() {
static int allocations = 0;
++allocations;
if(allocations == 3)
{
//produce exception
throw 1;
}
cout << "ctor" << endl;
}
~test()
{
cout << "dtor" << endl;
}
};
int main()
{
//works
auto oneInstance = new test;
//doesnt work
try {
auto manyInstances = new test[3];
}
catch(...)
{
cout << "error?";
}
}
This prints:
ctor ctor dtor error?
Yes, delete[] guarantees destructors are called on every object.
When something is created using dynamic memory allocation, it is the programmer's responsibility to delete it. So compiler doesn't bother. In the case where the destructor is declared private, an instance of the class can also be created using the malloc() function.
Can there be more than one destructor in a class? No, there can only one destructor in a class with classname preceded by ~, no parameters and no return type.
Yes, destructor can be private and it is not true that class cannot be instantiated.
Whenever an array of the object of a class is created at runtime then it is the programmer’s responsibility to delete it and avoid a memory leak: Constructor is called! Constructor is called! Constructor is called! Writing! Writing! Writing! Destructor is called! Destructor is called! Destructor is called!
In C++, the single object of the class which is created at runtime using a new operator is deleted by using the delete operator, while the array of objects is deleted using the delete [] operator so that it cannot lead to a memory leak. Writing code in comment? Please use ide.geeksforgeeks.org , generate link and share the link here.
Assuming your class is next to trivial, the reason for the error could be that two of your NameClass objects have an array pointer that points to the same array. This can happen if your class does not have a user-defined copy constructor and/or assignment operator, in which case the compiler will generate one for you.
It's because of exceptions, the array version of new[]
has to go and call the destructor on elements that have been previously allocated when an exception propagates to ensure exception safety. The single element new
does not need to do that. If allocation fails, it just fails, no need to destroy anything.
§ 8.3.4 New [expr.new/20]
If the new-expression creates an array of objects of class type, the destructor is potentially invoked
Regarding your edit, see the following quote from the C++17 standard
§ 8.17 Throwing an exception [expr.throw/4]
If no exception is presently being handled, evaluating a throw-expression with no operand calls
std::terminate()
Regarding your second edit, you have missed counting an instance of test
that you created via new
(not new[]
), that leads to the first instance of test
being created, that's where the confusion about number of constructions comes from.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With