class contains a pointer to a member copy
Title: The following is the declaration of the class and the executed array. Problem. And put forward several solutions to the existing problems.
Template<typename t> class Array{public: Array (unsigned arraySize):d ata (0), size (arraySize) { if ( Size > 0) data = new t[size]; } ~array () { if (data) delete[] data; } void SetValue (unsigned index, const t& value) { if (Index < size) Data[index] = value; } T getValue (unsigned index) const { if (Index < size) return data[index]; else return T (); } Private: t* data; unsigned size;};
Analysis: We note that the inside of the class encapsulates a pointer to store the array data. Most problems with software often boil down to the wrong handling of pointers.
This class simply provides a constructor. The construct copy function and the overloaded copy operator function are not defined. When the user of this class declares and instantiates an instance of the class in the following way:
Array A (10);
Array B (A);
Or assign one instance of the class to another instance in the following way
Array A (10);
Array B (10);
B=a;
The compiler calls its own active-generated construction copy function or the overloaded function of the copy operator . The compiler generates a default overloaded function that constructs copy functions and copy operators, and the pointer is a bitwise copy, but copies the address of the pointer without copying the contents of the pointer. So after running through the previous code. The same address that A.data and B.data point to. Data is deleted when a or B is arbitrarily terminated in its life cycle when the destructor is called. Because their data points to the same place. Data for two instances has been deleted.
But another example does not know that its data has been deleted, and when attempting to use its data again, the program will inevitably crash.
because the problem occurs because of the overloaded functions that call the compiler-generated default construct copy function and copy operator. one of the simplest ways to do this is to disallow the use of these two functions. so we can declare these two functions as private functions, assuming that the user of the class attempts to invoke these two functions, it will not be compiled. The implementation of the code such as the following:
Private: Array (const array& copy); Const array& operator = (const array& copy);
The problem with the original code is that because the data of the different instances points to the same address, deleting one instance of data will also delete the data of the other instance. So we can also make copies of the overloaded functions that construct copy functions or copy operators not just addresses, but data. Since we have stored a copy of the data again, there is no effect on another instance when one instance is deleted. This idea we call deep copy . The implementation of the code such as the following:
public:array (const array& copy):d ata (0), size (copy.size) {if (Size > 0)//There is no self-copy check here, ask the reader to think about how to resolve { data = new T[size]; for (int i = 0; i < size; ++i) SetValue (i, Copy.getvalue (i)); }} const array& operator = (const array& copy) {if (this = = ©)//Self-assignment check retur n *this; if (data! = NULL) {delete[]data; data = NULL; } size = Copy.size; if (Size > 0) {data = new t[size]; for (int i = 0; i < size; ++i) SetValue (i, Copy.getvalue (i)); } }
To prevent multiple pointers to data being deleted multiple times, we can also save how many pointers point to that data. It is only when there is no pointer pointing at the data that the ability to be removed is sufficient. The idea of In the constructor, the reference count is initialized to 1 Span style= "Color:rgb (237,125,49)"), whenever you assign this instance to another instance or to a constructor copy function that passes a number of parameters to another instance. Reference count plus 1 because this means that one more instance points to its data data when assigned to other data, the reference count is reduced 1 data The pointer is one less.
When the reference count is reduced to 0 ,thedata is no longer in any instance pointing to it, and can be safely removed at this time.
The implementation of the code such as the following:
Public: Array (unsigned arraySize) :d ata (0), size (arraySize), COUNT (new unsigned int) { *count = 1; if (Size > 0) data = new t[size]; } Array (const array& copy) : Size (copy.size), data (Copy.data), COUNT (Copy.count) { + + (*count); } ~array () { Release (); } Const array& operator = (const array& copy) { if (data = = Copy.data) return *this; Release (); data = Copy.data; size = Copy.size; Count = Copy.count; + + (*count); } Private: void Release () { ---(*count); if (*count = = 0) { if (data) { delete[]data; data = NULL; } Delete count; Count = 0; } } unsigned int *count;
Please indicate the error, reprint please indicate the source, thank you!
Copyright notice: This article Bo Master original article. Blog, not reproduced without consent.
The rookie series of C + + classic question (vi)