answersLogoWhite

0

If memory is unused then it does not need to be freed. Unused memory is unallocated memory, and all unallocated memory belongs to the system.

In order to use memory you must first allocate it. To keep track of that allocation you must maintain a pointer to it, and must release that allocation when it is no longer required. Allocating memory you don't actually need is extremely wasteful, therefore it is always best to allocate memory as and when it is actually required, and release that allocation as soon as it is no longer required. If there's ever an occasion where allocated memory is "unused" then you must question why you allocated the memory in the first place.

As to what code to place in the destructor to release an allocation, you must first ascertain whether that memory belongs to the class or is shared with other instances of the same class. If the memory is shared, then, in the absence of a reference counting mechanism, no instance can own the memory -- it must be allocated outside of the class and released outside of the class. in this case, each instance of the class need only copy the pointer's value, not what it points to (a shallow copy).

For classes that own an allocation, you not only have to release that memory upon destruction, you must also ensure the copy constructor and assignment operator perform a deep copy of the memory. This means you cannot rely upon compiler generated constructors nor assignment, as they will only perform a member-wise copy (another term for shallow copy).

If you have a mutator (setter), a deep copy must be performed there also. Both the assignment operator and the mutator must also check for self-references before releasing any existing allocations prior to making a deep-copy. In addition, any accessor (getter) must also return a deep-copy of any allocation in order to maintain encapsulation of the member pointer (if you return a shallow copy, there's always a danger the memory will be released from outside of the class, which is never a good thing).

The following example demonstrates a class that owns allocated memory. For the sake of simplicity, the memory simply contains an integer, but all allocations are treated the same regardless of the type or complexity. Simple replace all occurrences of 'int' with whatever class of object you intend to use.

Note that if the object being pointed at must be guaranteed to exist at all times, then it is better (safer) to use an embedded member object (with static allocation) instead of using dynamic allocation (in other words, use an int variable rather than a pointer to int). However, the following example does NOT guarantee the object's existence, but must take ownership of any allocation passed to it. Hence the prevalent use of deep-copy and tests for NULL and self-references. Note also the use of the tertiary conditional operator (?:) to test for NULL pointers.

class foo

{

public: // construction and assignment.

foo(void);

foo(const int& i);

foo(const foo& f);

foo& operator=(const foo& f);

~foo(void);

public: // mutator.

void set_data(int* d);

public: // accessor.

int* get_data() const;

private: // member.

int * m_data;

};

// Default constructor. Initialises object to NULL.

foo::foo(void):m_data(NULL){}

// Overloaded constructor. Initialises object by reference.

foo::foo(const int& i):m_data(new int(i)){}

Note that although the default and overloaded constructor could be combined into a single default constructor with a default by-value parameter [foo::foo(const int i=0);] this means the allocation must be guaranteed to exist and therefore a member pointer would be superfluous (an embedded member object would be safer). The only suitable alternative would be to pass a pointer with a default of NULL, as shown here:

// Combined default and overloaded constructor:

foo::foo(int* p=NULL):m_data(p?new int(*p):NULL){}

The remainder of the class implementation follows:

// Copy constructor. Deep-copy.

foo::foo(const foo& f):m_data(f.m_data?new int(*f.m_data):NULL){}

// Assignment operator overload. Deep copy.

foo& foo::operator=(const foo& f)

{

// Check for self-reference.

if( this != &f )

{

// Release the existing allocation and deep-copy.

if( m_data )

delete( m_data );

m_data=f.m_data?new int(*f.m_data):NULL;

}

// Return this instance by reference.

return( *this );

}

// The all-important destructor:

foo::~foo( void )

{

// Release allocation.

if( m_data )

delete( m_data );

}

// Mutator.

void foo::set_data(int* d)

{

// Check for self-reference.

if( d != m_data )

{

// Release and deep-copy.

if( m_data )

delete( m_data );

m_data = d?new int(*d):NULL;

}

}

// Accessor: returns a deep copy (caller must release the copy).

int* foo::get_data(void) const

{

return(m_data?new int(*m_data):NULL);

}

User Avatar

Wiki User

12y ago

What else can I help you with?

Continue Learning about Engineering

Why java does not support destructor?

AMIT KUMAR3th Nov , 2014Java does not support destructors, since java supports the concept of garbage collection,hence the garbage collector is used to automatically free the space which has occupied by the program while running.Garbage collector calls the finalize() method which is defined in the object class. finalize() method is called once for each object.


What are the advantages of constructor and destructor?

Without a copy constructor the only way to copy an object would be to instantiate a new object (or use an existing object) and then assign another object's value to it. However, it would be very odd indeed to have a copy assignment operator without a matching copy constructor. If you have one, you must have both. If you do not need to copy an object of a particular class, however, you can simply delete both the copy constructor and the copy assigment operator for that class. Any attempt to copy or copy assign would then result in a compile-time error.


What is data segment memory and code segment memory?

Code Segment, in which all the application code is stored Data Segment, that holds the global data


What is the difference between the constructor to and destructor?

Functions and Constructors are similar in many ways. They can have arguments, they can have any amount of code, they can access the class's variables etc. the only difference is that a method in java needs to mandatorily have a return type but a Constructor in java cannot have a return type. It always creates and returns an object of the class for which it is the constructor. You cannot return a value from a constructor explicitly and if you try to do that, the compiler will give an error. The system knows that the purpose of the constructor is to create an object of the class and it will do the same irrespective of whether you declare a return type or not.


Why use new and delete operator overloading in c plus plus?

one reason to use new and delete operator overloading in c++ is when you are using your own memory manager code. when the user of your code calls the new keywork, your memory manager code can allocate memory.