> Every time you use new keyword, there should be also delete keyword.
The general rule is easier to remember:
If we acquire a resource, we must release it after we are done with using it.
The resource involved could be anything: memory from the free store, a file that is opened, a lock on a database, a socket bound to an address ...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
// acquire a resource
std::FILE* file = std::fopen( "myfile", "r" ) ;
// use the resource
// int c = std::fgetc(file) ;
// etc...
// release the resource
std::fclose(file) ;
// acquire a resource
int* a = new int[123] {0} ;
// use the resource
// a[0] = 9 ;
// etc...
// release the resource
delete[] a ;
|
When resources are acquired dynamically, doing this manually is error-prone; we may attempt to use a resource after it has been released, we may try to release a resource that had already been released, we may parasitically continue to hold on to the resource for long periods after we are done with using it, and (what is most commonly pointed out) we may not release it at all. Automating the process of managing resources makes life a lot simpler. So:
1 2 3 4 5 6 7 8 9 10 11 12
|
void foo()
{
// prefer this; resource management is automated
int a[123] {0} ;
// the resource is tied to the scope, and is automatically released when the scope ends
// either via a normal return or because of a thrown exception
// to this: resource management is our headache
int* b = new int[123] {0} ;
// ...
}
|
A few programming languages (C++, Ada and the sill-born D) support RAII - the mechanism of associating a resource with the duration in which it can be used, and then automatically releasing the resource as soon as its use is over. So in C++, we would much rather write:
1 2 3 4 5 6 7 8
|
std::ifstream my_file( "myfile" ) ;
std::vector<int> seq( 123 ) ;
// if we must
std::unique_ptr< int[] > array( new int[123]{0} ) ;
// if we really must
std::shared_ptr<std::FILE> c_file( std::fopen( "file2", "r" ), std::fclose ) ;
|