C++ Principles to note when using new and delete

  • 2020-11-18 06:23:09
  • OfStack

Dynamic memory management of C++ is accomplished through new and delete operations, namely new to apply for space and delete to free space. Note the following principles when using new and delete.

1.new and delete correspond to 11

If the application is successful, you must release the space with delete at some later point, without forgetting to release or releasing it more than once. The former causes memory leaks and the latter causes runtime errors. The following program.


#include <iostream>
using namespace std;

int main()
{
	int *p;
	p=new int(3);
	if(p)
	{
		delete p;
	}
	delete p;
	return 0;
}

The above program releases the space that the pointer p points to twice. This memory error is very harmful to THE C++ program, which is also the reason why many people forget C++. Freeing the same block of memory multiple times does not necessarily cause an immediate program error or a crash, depending on the specific compiler implementation. However, freeing the same block of memory multiple times is definitely a programming error that can cause other logic errors at a later point in time, making debugging and error correction difficult. Consider the following procedure.


#include <iostream>
using namespace std;

int main()
{
	int *p,*q,*one;
	one=new int;
	if(one)
	{
		cout<<one<<endl;
	}
	delete one;
	p=new int(3);
	if(p)
	{
		cout<<p<<endl;
	}
	delete one;// Suppose the programmer accidentally added this statement 
	q=new int(5);
	if(q)
	{
		cout<<q<<endl;
	}
	cout<<(*p)+(*q)<<endl;
	delete p;
	delete q;
}

After the program is compiled, the running results are as follows:

[

003289A0
003289A0
003289A0
10

]

There will be an interrupt during the running of the program. From the output of the program, it can be seen that after freeing the space pointed to by the pointer one, the space applied for the pointer p is the space pointed to by the original one. Because delete one was used again after allocating space for p by accident, the space applied for by q was the space applied for by p. In this way, the value assigned to *q overwrote the value of the cell pointed to by p, resulting in the final output of 10. Thus, multiple releases of the same block of memory space, even if it does not cause the program to break, will damage the environment and cause confusion in the membership relationship between the pointer and the corresponding space, thus leading to logic errors. In a large program design, this kind of logical error finding can become 10 minutes and laborious.

** Note: ** When the pointer p has a value of NULL, using delete p multiple times is not a problem because freeing the space for a null pointer does not actually cause any operation. So, setting the "don't use" pointer to NULL is a good programming practice.

2.new[] corresponds to delete[] by 11

The new[] operator is needed to apply for an array of objects, and the delete[] operator is needed to release the array of objects. This point is different from C, where the malloc()/free() function is used for both single and multiple objects. First look at the difference between the delete and delete[] operators.


class Test 
{
public:
	Test() { cout<<"ctor"<<endl; }
	~Test() { cout << "dtor" << endl; }
};

//segment1
Test* pArray1 = new Test[3];
delete pArray1;

//segment2
Test* pArray2 = new Test[3];
delete[] pArray2;

The results of the code snippet segment1 running are as follows:

[

ctor
ctor
ctor
dtor

]

The operation results of segment2 are as follows:

[

ctor
ctor
ctor
dtor
dtor
dtor

]

It can be seen that the difference between delete and delete[] is that when releasing the object array, delete only calls the destructor once, while delete[] calls the destructor three times, completing the release of the object array. In fact, when using new and new[] to apply for memory space, an additional section of memory will be requested to hold the memory space size, number of elements and other information requested by the user. When delete[] is used to free the memory space, the object's destructor is called one by one and the final memory space is freed. When you use delete to release an array of objects, only the destructor of a single object is called, causing a memory leak. The symbol [] tells the compiler to get the number of elements held in delete1 block of memory, and then clean up 11. Therefore, using delete to free the memory space requested by new[] and using delete[] to free the memory space requested by new are both wrong practices.

For specific use, the following two points should be paid attention to:

(1) For built-in data types, using delete and delete[] has the same effect because there are no constructs and destructors. Such as:


int* pDArr=new int[3];
//processing code
delete pDArr;	// Is equivalent to delete[] pDArr

For built-in data types, it is possible to use delete to free the memory space of the object array, but it is recommended to use delete[] for the readability of the code. Therefore, the use of new[] and delete[] should correspond to 11.

(2) For programmers who use typedef frequently, it is easy to mix new[] with delete, such as:


typedef int Height[NUM] ; 
int* pHeight=new Height;

Should delete or delete[] be used in this case? The answer is as follows:


delete	pHeight;		//wrong But easy to use by mistake delete
delete[] pHeight;	//right

To avoid the above error, it is recommended not to use typedef for arrays, or to use vector in STL instead of arrays.

3. new/new[] in the constructor corresponds to delete/delete[] in the destructor needs 11

When a class has pointer variables in its members, it is a "standard" and safe practice to apply new to space in the constructor and delete to free space in the destructor. For example, the following program.


#include <iostream>
using namespace std;

class Student
{
	char* name;
public:
	Student()
	{
		cout<<"Default constructor"<<endl;
	}
	Student(char*);
	~Student();
};

Student::Student(char*s)
{
	//Student();// The constructor cannot call another constructor 
	cout<<"In constructor,allocating space"<<endl;
	name=new char[strlen(s)+1];
	strcpy(name,s);
	cout<<"name:"<<name<<endl;
}

Student::~Student()
{
	cout<<"In destructor, free space"<<endl;
	delete name;
}

int main()
{
	Student s1(" zhang 3");
}

Program output:

[

In constructor,allocating space
name: 3
In destructor, free space

]

Since any 1 object is called only once by its constructor and only once by its destructor, it is guaranteed that the new and delete operations at run time correspond to 11 and memory management is guaranteed.

In C++, one constructor cannot call another constructor of this class, in order to prevent constructors calling each other from breaking this correspondence between memory requests and releases.

The above is C++ new and delete to pay attention to the detailed content of the principle, more information about C++ new and delete please pay attention to other related articles on this site!


Related articles: