I am working on an implementation of a binary tree in C++. I am fairly new to the language, and while I understand what structs and destructors are, I am not sure about what happens with nested classes/structs.
In my implementation, I have a nested struct for my binary node. Does this struct need its own destructor, or will all of the nodes be deleted when the destructor for the binary tree itself get called. Does the answer change if I change the struct to a class?
Also, I was told that if you ever call "new" in a class, you need to call "delete" in the destructor. If I initialize an array in my initialization list for a class (i.e. class: array({0})), do I need to delete [] array in my destructor?
Nesting one class (or struct) within another has no effect on the lifetime of the objects. All it does is provide a scope for the class's name, and access to private members in the enclosing class. So your tree nodes won't be automatically destroyed just by virtue of being nested in the tree class.
If you want a tree's nodes to be destroyed when the tree itself is destroyed, you need to ensure that the tree's destructor does that. If you're allocating the nodes manually with new, use delete (or delete[]) in the destructor. Alternatively, you can use something like std::auto_ptr (or std::unique_ptr in C++11), which will do the cleanup in its own destructor so you don't have to write the delete calls yourself.
Changing a struct to a class has no effect on its behavior at runtime. The only difference between a struct and a class in C++ is that a struct's body implicitly begins with public: and a class's body implicitly begins with private:.
it is not necessary for C++ that we have to define destructors in our class/struct.
there is no any changes in destructor if you are going to change struct to class.
but it is good for programming language that if we call memory with new, we have to delete it ourself.
if you are going to define nested class than it is good to make destructor in that class also.
there is no need to use for delete[] for array.
Related
Is there a way to design a class, that neither it nor its descendants can be allocated automatically (on stack), but only dynamically (in heap)?
I have a 3D scene represented by a scene tree, each object has a parent and a number of children. All scene objects are inherited from some base class SceneObject. I would like to make it impossible to allocate such objects on the stack.
The only way I know to achieve this for a class is to declare a protected constructor and provide a factory (see Is it possible to prevent stack allocation of an object and only allow it to be instantiated with 'new'?). This does indeed work as I want for the class, but not for its descendants. Authors of derived classes need to explicitly declare constructors as non-public and I have no way to control it, thus providing possibilities for an error.
Are there any possibilities to achieve what I want? Any compromises maybe?
Not really, no.
You may be able to screw around with explicitly overriding operator new, or to mix the answer you linked to with templates, but otherwise you're hosed.
I'm going to go off on a limb and guess that your full problem involves resource management; if that's the case, check out the rule of three; if your class has a user-defined destructor, copy constructor, or copy assignment (operator=(const Something&)), you probably need all three.
The only way I know to do this is how your linked answer says - declare the class's constructor as private so nobody but the class itself can create instances of it, and then provide a public static method that creates an instance of the class on the heap. Everyone who wants an instance must call the static method.
I'm trying to validate my understanding of C++ destructors.
I've read many times that C++ supplies a default destructor if I don't write one myself. But does this mean that if I DO write a destructor that the compiler WON'T still provide the default cleanup of stack-allocated class fields?
My hunch is that the only sane behavior would be that all class fields are destroyed no matter what, whether I provide my own destructor or not. In which case the statement I've read so many times is actually a little misleading and could be better stated as:
"Whether or not you write your own destructor, the C++ compiler always
writes a default destructor-like sequence to deallocate the member
variables of your class. You may then specify additional
deallocations or other tasks as needed by defining your own destructor"
Is this correct?
When an object is cleaned up in C++, the language will
First call the destructor for the class, then
Call the destructors for all the fields of the class.
(This assumes no inheritance; if there's inheritance, the base class is then destroyed by recursively following this same procedure). Consequently, the destructor code that you write is just custom cleanup code that you'd like to do in addition to the normal cleanup code for individual data members. You won't somehow "lose" the destructors for those objects being called as normal.
Hope this helps!
Yes -- any object contained within your object will be destroyed as part of destroying your object, even if/though your destructor does nothing to destroy them.
In fact, your destructor won't normally do anything to destroy objects contained within the object; what it typically does is destroy objects that are remotely owned via something in the object (e.g., a pointer to an object, a handle to a network or database connection, etc.)
The only exception to this that's common at all is if your object contains a buffer of some sort, and you've used placement new to construct something into that buffer. If you use placement new, you normally plan on directly invoking the dtor as well. [Note that "common" is probably overstating how often you see/use this--it's really quite uncommon, but the other possibilities are much rarer still.]
Yes. Even if you DO write a destructor, the C++ compiler will create a sequence. Consider the following code:
class foo{
int a;
}
Write a destructor that deallocates a, a stack-allocated variable... its impossible. Therefore, even if you write your own destructor, a C++ compiler MUST generate one to deallocate stack objects.
I have created a class, and according to the textbook Accelerated C++ by Andrew Koenig and Barbara E. Moo,
The work of the destructor is to do any cleanup that should be done whenever an object goes away. Typically this cleanup involves releasing resources, such as memory, that the constructor has allocated.
I am trying to write a destructor, and I'm getting confused by all the code floating out there. Sometimes a simple deconstructor like this is used ~MyIntArray() {} and sometimes there are things between the {}.
What is the rule behind putting things between the curly brackets or not? Is it just containers e.g. lists, arrays, vectors, pointers that need to be placed between the curly brackets (these are the things I see in code examples out there).
edit: this is my class in case that's needed
class msgInfo
{
public:
msgInfo();
msgInfo(int, int, int, std::string, std::list<int>);
private:
int source_id;
int dest_id;
int priority;
std::string payload;
std::list<int> nodePath;
};
Rule 1:
Rule of three in C++03 or rule of five in C++11.
If your class needs a user defined copy constructor or a copy assignment operator then it most likely needs a user defined destructor.
When do you need either of these 3?
When your class has dynamically allocated pointer members and you need to maintain lifetime of each separate from that of another instance member. For e.g: char * member.
When you manage resources. For e.g: Open file handles, mutex locks etc.
Rule 2:
If your class is intended to be used for derivation and you need polymorphic deletion of objects then you must mark the destructor in Base class as virtual.
Well, if you allocated resources dynamically (new etc..) then in the destructor you'd want to release them (delete), in your case, since all of your members are not allocated dynamically, your destructor can be empty ( or non existent).
Another note worth mentioning is, if you do end up implementing the destructor, and you plan on someone inherting your class, you should make it virtual.
It is a good programming practice to provide a destructor in your C++ program even if there is no explicit need for one. In your code you might not have any dynamic memory allocation, so the destructor provided is simply ~MyIntArray() {} without any code inside.
Please also read the Wikipedia article on Rule of Three in C++.
http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)
If you don't provide a destructor, the compiler will provide one for you. This automatically-generator destructor will correctly call the destructors of all of your class's data members, such as payload etc.
If you don't need to do anything beyond that then you don't need to explicitly provide a destructor. Alternatively, an empty one would work equally well.
If, on the other hand, your constructor allocates some resources (for example, connects to a database), then typically you'd need to put some code in your destructor to release that resource (e.g. disconnect from the database). This is the standard C++ idiom used to prevent resource leaks.
Your class does not have any resources that need to be dealt with in the destructor: each type is either built-in (`int) or handles its own resources (std::string,std::list`). So you do not need to implement your own destructor. The compiler will provide one that is equivalent to the empty braces one.
You would need to implement your own if your class had resources that need dealing with: dynamically allocated objects, handles or connections to sockets, databases, reference counts, etc.
One situation where it might make sense to implement an empty destructor is when you have a class which is intended to be derived from and used polymorphically. In this case, a virtual destructor is needed (there are many SO posts about that), and it is common practice to provide an empty implementation so that derived types to not have to implement it themselves when there are no resources to deal with.
virtual ~Foo() {}
A class like this doesn't need a non-trivial destructor (one, with "things between the curly brackets").
In a destructor, you must release resources, you have "manually" allocated. For example:
if you have new/new[] in the constructor and you need to free this memory in the destructor
if you have opened a file in the constructor, close it in the destructor
if you have locked a mutex in the constructor, unlock it in the destructor
Things like this.
Also, you may need some additional logic to be implemented, when an object is being destructed. Depends on what you're trying to do.
A definition of a destructor should, as far as I know or am concerned, should always look like this:
~msgInfo() { /* free stuff */ }
A constructor on the other hand may look like this:
msgInfo(): m_var1(0), m_var2("Initialize") { /* further initialization */ }
Where what comes between : and { is member variable initialization.
In the destructor you should deallocate anything which was dynamically allocated elsewhere in the class, hence the : notation is no good, since you probably need to do delete on the objects.
In your code you might not have any dynamic memory allocation,so you don't need to provide a destructor.
So I have the standard C++ setup with an object that stores another object. The stored object is owned completely, it's never leaked to the outside. The member is non-const.
class Container
{
private:
Contained item;
}
As I understand, when my Container is instantiated the default constructor will be called on the item member and I don't have to manage it in the initializer list.
Also do I understand it correctly that when my object is destroyed the dtor on the item will be called automatically?
Another option would be to store it by reference of course
class Container
{
private:
Contained& item;
public:
Container() : Contained()
{
}
}
in which case I don't know whether I should delete it in the dtor.
Yet another option is to store it by ptr
class Container
{
private:
Contained* item;
public:
Container()
{
item = new Contained();
}
~Container()
{
delete item;
}
}
Knowing that my item never gets returned to the caller and never bleeds into the outside API and never gets reassigned, what is the best way to proceed? As I mentioned, the item member is not const
(it will be a self-resizing data structure).
The easiest is to store the object itself. Using reference for this purpose is, I would say, confusing. One advantage with using the pointer is that you then may be able to avoid defining the Contained type in the header file - you can instead forward declare Contained, and keep all the details inside the .cpp file.
The first way is the best way in my opinion (it appears you don't need the object to be lazily constructed). The second way requires that you pass in the object from the outside and that it's lifetime is guaranteed, and the third way is really only good if you want lazy instantiation (i.e. only create the object on first use).
In this case, it's best to store the object itself, yes. Storing it by reference will only create an alias to the object, so your class is not the actual owner. Storing via a pointer is useless, unless your object is a base class and you might want to store a derived object.
Contrary to Luchian Grigore, I’d go for pointer/reference method: storing the encapsulated object as a reference or pointers lets you forward-declare it, hence saving compilation time.
In addition to that, it lets you have init() and destroy() member functions that would in turn call the constructor and destructors of the encapsulated object, as well as perform initialization of the other parts of the object. This way, a bad initialization can be handled by the return value of init().
Most of the time, you want to reduce the dependencies on your class. If this class forms an integral part of the interface (even if the member is private) then you can assume that anyone using your class will be using this one.
In such a case, having it as a member variable makes sense.
Where it is an implementation detail of your class, you should hide this detail from the users by using a forward declaration, so use a type that allows a forward declaration.
It is highly unlikely that it will be a reference. A reference must be initialsed on construction of your class, and so the constructor would probably have to pass in the object it refers to. Declaring it with new and dereferencing is going to lead to confusion.
If it is a pointer, your class can manage its lifetime with the destructor. In this case I often will use a raw pointer as it is well under control and my destructor can happily delete it, assuming my class is non-copyable.
If you use shared_ptr, you can use a forward declaration. But beware that your semantics are now that if you copy your object, all the copies will have a pointer to the same underlying object. If this is not what you want, shared_ptr is probably wrong. In addition, if you use shared_ptr when your class is non-copyable, it isn't really shared.
So unless you can use unique_ptr which allows a forward declaration, I would go for the raw pointer and a non-copyable class.
If your member does remain an implementation detail but is something that is pretty standard, like a map or a vector, it is not worth "encapsulating it" to the extent of using a forward declaration, only the types that are contained within the map or the vector, but not the map or vector itself.
Here is my issue:
My base class has a constructor that takes in a class pointer, if that pointer is NULL, it knows to instance it itself and maintain it.
The problem is, in the base destructor, I have to unregister that pointer with something private of base. So what happens is when I try to make a call to the class pointer in the base destructor and the derived is maintaining it, it has already been freed. So that causes a problem. What could I do?
Thanks
If the base class creates an instance for the pointer, why can't it free it as well? Is there anything stopping you from moving the free into the base destructor?
It's always best to be consistent in terms of who does what, at a certain level of hierarchy- splitting up the same responsibility across several levels of hierarchy will surely lead to problems such as this. Not to mention, if you want to create another class that inherits from base, you will have to re-implement this management in the new class as well, creating code duplication.
The order of constructors and destructors in inheritence is opposite; the base constructor is called before any of it's derived constructors. Upon delete, the inverse happens - the derived class is deleted first.
To solve your problem, could the base destructor not test whether its private instance is not NULL?
The base class could implement a protected member function to do the cleanup, then the derived destructor could call this helper function before destroying the resource.
From your description I gather that sometimes the derived class will be in charge of this pointer, and sometimes the base class will be. The simplest solution I can think of is to add a boolean in your base class that will allow you to track who owns the object. If the base class has initialized the pointer, set the boolean to true. Then your destructor can check who owns the object and in turn whether it should clean up.
A better solution would be to use boost:shared_ptr. This is a reference counting pointer abstraction that will automatically cleanup your object when its last reference goes out of scope. With this abstraction you generally don't need to worry about who releases your pointer.
If your constructor allocates memory, the corresponding destructor is responsible for freeing it. If you conditionally allocate memory, then you need to conditionally free it. A Boolean flag would help you determine if allocation occurred.
Another solution is to use a reference counting. At the time of the allocation the reference count shall be 1. If another class has interest in the object, it retains the pointer by increasing the reference count. If a class is no longer interested in the object, it decreases the reference count. When the counter reaches 0, the object must be deleted. shared_ptr is a standard C++ reference counted auto pointer implementation, which works very well in complex mixed ownership situations.