Difference between revisions of "Dynamic Memory Allocation in C++"
Proj user18 (talk | contribs) (→Dynamic Memory Allocation) |
Proj user18 (talk | contribs) (→Dynamic allocation of objects) |
||
(23 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
+ | |||
= Dynamic Memory Allocation = | = Dynamic Memory Allocation = | ||
Certain memory requirements of a program can be determined before program execution. In such a case, variables can be declared appropriately. However, there are cases when the memory requirement can be known only during run-time. In such cases, dynamic memory allocation is required. | Certain memory requirements of a program can be determined before program execution. In such a case, variables can be declared appropriately. However, there are cases when the memory requirement can be known only during run-time. In such cases, dynamic memory allocation is required. | ||
The lifetime of the objects created using dynamic memory allocation is not limited by the scope in which they were created. | The lifetime of the objects created using dynamic memory allocation is not limited by the scope in which they were created. | ||
+ | Dynamic memory is allocated in the heap. | ||
Dynamic memory allocation and deallocation in C++ is achieved using operators new and delete.<br> | Dynamic memory allocation and deallocation in C++ is achieved using operators new and delete.<br> | ||
Line 24: | Line 26: | ||
A block of memory for 5 integer data is allocated and a pointer to the start of the memory block is returned. | A block of memory for 5 integer data is allocated and a pointer to the start of the memory block is returned. | ||
<br> | <br> | ||
+ | |||
+ | |||
+ | |||
+ | There are 2 ways to check if the memory allocation was successful:<br> | ||
+ | |||
+ | |||
+ | '''Exceptions:'''<br> | ||
+ | If the allocation fails, <span style="color:#FF0000">bad_alloc</span> exception will be thrown which needs to be handled.<br> | ||
+ | new uses exception method by default.<br> | ||
+ | <syntaxhighlight lang="c"> | ||
+ | int *data = new int; //bad_alloc exception is thrown if allocation fails | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | '''nothrow''':<br> | ||
+ | If allocation fails, the pointer returned is a null pointer. In this case, it is advisable to check if the pointer returned is valid before using it. | ||
+ | <syntaxhighlight lang="c"> | ||
+ | int *data = new (nothrow)int; | ||
+ | if(data == nullptr) | ||
+ | { | ||
+ | // Memory allocation failed. | ||
+ | } | ||
+ | </syntaxhighlight> | ||
==delete== | ==delete== | ||
Line 33: | Line 58: | ||
<br> | <br> | ||
In the first expression, memory allocated to a single element is released.<br> | In the first expression, memory allocated to a single element is released.<br> | ||
− | Example: | + | <syntaxhighlight lang="c"> |
+ | Example: delete data; | ||
+ | </syntaxhighlight> | ||
In the second expression, memory allocated to an array of elements is deleted. <br> | In the second expression, memory allocated to an array of elements is deleted. <br> | ||
− | Example: | + | <syntaxhighlight lang="c"> |
+ | Example: delete[] data; | ||
+ | </syntaxhighlight> | ||
<br> | <br> | ||
Line 42: | Line 71: | ||
= Dynamic allocation of objects = | = Dynamic allocation of objects = | ||
− | == | + | Objects can be allocated and deallocated dynamically similar to other basic types using '''new''' and '''delete'''. |
+ | |||
+ | When '''new''' is used to create an object, constructor is invoked.<br> | ||
+ | <syntaxhighlight lang="c"> | ||
+ | TestClass *obj1 = new TestClass; // Default Constructor is invoked. | ||
+ | TestClass *obj2 = new TestClass(10); // Parameterized Constructor is invoked | ||
+ | TestClass *obj3 = new TestClass[5]; // Dynamic array of 5 TestClass Objects is created | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | When '''delete''' is used to deallocate an object, destructor is invoked. <br> | ||
+ | <syntaxhighlight lang="c"> | ||
+ | delete obj1; | ||
+ | delete obj2; | ||
+ | delete [] obj3; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == '''Constructor''' == | ||
A constructor is a special member function of the class which is invoked when we create new instances of the class. | A constructor is a special member function of the class which is invoked when we create new instances of the class. | ||
Line 78: | Line 123: | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | + | ||
TestClass::TestClass() : data(nullptr), num_data(0) | TestClass::TestClass() : data(nullptr), num_data(0) | ||
{ | { | ||
Line 88: | Line 133: | ||
Parameterized constructor accepts parameters which can be assigned as initial values to the member variables. | Parameterized constructor accepts parameters which can be assigned as initial values to the member variables. | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | + | ||
TestClass::TestClass(int length) : data(nullptr), num_data(length) | TestClass::TestClass(int length) : data(nullptr), num_data(length) | ||
{ | { | ||
Line 95: | Line 140: | ||
− | === | + | === Copy Constructor === |
+ | Copy constructor is invoked when an object is initialized using another object of the same type. | ||
+ | <syntaxhighlight lang="c"> | ||
+ | |||
+ | TestClass::TestClass(const TestClass& anotherObject) | ||
+ | { | ||
+ | num_data = anotherObject.num_data; | ||
+ | data = new int[num_data]; | ||
+ | |||
+ | for(int i=0; i<num_data; i++) | ||
+ | { | ||
+ | data[i] = anotherObject.data[i]; | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == '''Destructor''' == | ||
+ | A destructor is a special member function called when the object is no longer in use. The memory occupied will be freed. | ||
+ | |||
+ | <syntaxhighlight lang="c"> | ||
+ | |||
+ | TestClass::~TestClass() | ||
+ | { | ||
+ | if(data != nullptr) | ||
+ | { | ||
+ | delete [] data; | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | |||
+ | In C++, default constructors and default destructors are automatically invoked.<br> | ||
+ | Also, C++ has a provision for default Copy constructor. However, this is not always tailored to our requirements. Hence, it is a good practice to define our own copy constructor. | ||
+ | |||
+ | = Memory Leak = | ||
+ | Memory Leaks occur when memory is dynamically allocated but never deallocated. | ||
+ | Memory leak accumulates over time and the system may run out of memory. Hence, caution must be exercised while allocating memory dynamically. | ||
+ | |||
+ | |||
+ | = [[Dynamic Memory Interview Questions]] = |
Latest revision as of 00:29, 19 December 2016
Contents
Dynamic Memory Allocation
Certain memory requirements of a program can be determined before program execution. In such a case, variables can be declared appropriately. However, there are cases when the memory requirement can be known only during run-time. In such cases, dynamic memory allocation is required. The lifetime of the objects created using dynamic memory allocation is not limited by the scope in which they were created. Dynamic memory is allocated in the heap.
Dynamic memory allocation and deallocation in C++ is achieved using operators new and delete.
new
new allocates memory as requested and returns a pointer to the beginning of the block of memory allocated.
Syntax:
type *ptr = new type; type *ptr = new type[n];
In the first expression, memory is allocated for a single element and a pointer to the memory location is returned.
Example: int *data= new int;
In the second expression, memory is allocated for an array of ‘n’ elements of type type.
Example: int *data = new int[5];<br>
A block of memory for 5 integer data is allocated and a pointer to the start of the memory block is returned.
There are 2 ways to check if the memory allocation was successful:
Exceptions:
If the allocation fails, bad_alloc exception will be thrown which needs to be handled.
new uses exception method by default.
int *data = new int; //bad_alloc exception is thrown if allocation fails
nothrow:
If allocation fails, the pointer returned is a null pointer. In this case, it is advisable to check if the pointer returned is valid before using it.
int *data = new (nothrow)int;
if(data == nullptr)
{
// Memory allocation failed.
}
delete
delete operator is invoked to explicitly release the dynamically allocated memory.
Syntax:
delete ptr; delete[] ptr;
In the first expression, memory allocated to a single element is released.
Example: delete data;
In the second expression, memory allocated to an array of elements is deleted.
Example: delete[] data;
new and delete internally use constructors and destructors to achieve dynamic memory allocation.
Dynamic allocation of objects
Objects can be allocated and deallocated dynamically similar to other basic types using new and delete.
When new is used to create an object, constructor is invoked.
TestClass *obj1 = new TestClass; // Default Constructor is invoked.
TestClass *obj2 = new TestClass(10); // Parameterized Constructor is invoked
TestClass *obj3 = new TestClass[5]; // Dynamic array of 5 TestClass Objects is created
When delete is used to deallocate an object, destructor is invoked.
delete obj1;
delete obj2;
delete [] obj3;
Constructor
A constructor is a special member function of the class which is invoked when we create new instances of the class.
Consider a class TestClass:
class TestClass
{
public:
TestClass();
TestClass(int length);
TestClass(const TestClass& other);
~TestClass();
int get_num_data() const;
private:
int *data;
int num_data;
};
We can create objects using constructors in the following way:
TestClass ObjectOfTestClass(10);
Constructors are extremely useful as they allow us to assign initial values to member variables.
There are three types of Constructors:
Default constructor
Default constructor creates instances of a class without the need of an actual parameter list.
TestClass::TestClass() : data(nullptr), num_data(0)
{
}
Parameterized Constructor
Parameterized constructor accepts parameters which can be assigned as initial values to the member variables.
TestClass::TestClass(int length) : data(nullptr), num_data(length)
{
}
Copy Constructor
Copy constructor is invoked when an object is initialized using another object of the same type.
TestClass::TestClass(const TestClass& anotherObject)
{
num_data = anotherObject.num_data;
data = new int[num_data];
for(int i=0; i<num_data; i++)
{
data[i] = anotherObject.data[i];
}
}
Destructor
A destructor is a special member function called when the object is no longer in use. The memory occupied will be freed.
TestClass::~TestClass()
{
if(data != nullptr)
{
delete [] data;
}
}
In C++, default constructors and default destructors are automatically invoked.
Also, C++ has a provision for default Copy constructor. However, this is not always tailored to our requirements. Hence, it is a good practice to define our own copy constructor.
Memory Leak
Memory Leaks occur when memory is dynamically allocated but never deallocated. Memory leak accumulates over time and the system may run out of memory. Hence, caution must be exercised while allocating memory dynamically.