Solution to problems caused by dynamic memory allocation in C ++

Source: Internet
Author: User
Author: Jin Hao-hao Source: Tianji net responsible editor: Fangzhou suppose we want to develop a string class, which can easily process string data. We can declare an array in the class. Considering that sometimes the string is very long, we can set the array size to 200, but in general, there is no need for so much space, this is a waste of memory. By the way, we can use the new operator, which is very flexible, but there will be many unexpected problems in the class. This article is intended for this phenomenon. Now, we will first develop a wrong class. From the name, we can see that it is an imperfect class. Indeed, we have to deliberately make it happen to all kinds of problems, so that we can take the right remedy. Okay, let's get started!

Wrong. h:

# Ifndef wrong_h _
# Define wrong_h _
Class wrong
{
PRIVATE:
Char * STR; // store data
Int Len; // String Length

Public:
Wrong (const char * s); // Constructor
Wrong (); // default constructor
~ Wrong (); // destructor
Friend ostream & operator <(ostream & OS, const wrong & St );
};
# Endif

Wrong. cpp:

# Include <iostream>
# Include <cstring>
# Include "wrong. H"
Using namespace STD;
Wrong: Wrong (const char * s)
{
Len = strlen (s );
STR = new char [Len + 1];
Strcpy (STR, S );

} // Copy data

Wrong: Wrong ()
{
Len = 0;
STR = new char [Len + 1];
STR [0] = '/0 ';

}

Wrong ::~ Wrong ()
{
Cout <"this string will be deleted:" <STR <'/N'; // This line of code is reserved for convenience of observation.
Delete [] STR;
}

Ostream & operator <(ostream & OS, const wrong & St)
{
OS <st. STR;
Return OS;
}

Test_right.cpp:

# Include <iostream>
# Include <stdlib. h>
# Include "wrong. H"
Using namespace STD;
Int main ()
{
Wrong temp ("Skynet ");
Cout <temp <'/N ';
System ("pause ");
Return 0;
}

Running result:

Skynet

Press any key to continue...

As you can see, the above procedures are very correct and useful. However, we cannot be confused by superficial phenomena! Next, use the test_wrong.cpp file to replace the test_right.cpp file for compilation and check the result. Some compilers may be unable to compile at all!

Test_wrong.cpp:

# Include <iostream>
# Include <stdlib. h>
# Include "wrong. H"
Using namespace STD;
Void show_right (const wrong &);
Void show_wrong (const wrong); // note that the parameter is passed by value instead of reference.
Int main ()
{
Wrong test1 ("first example. ");
Wrong Test2 ("second example. ");
Wrong test3 ("third example. ");
Wrong test4 ("fourth example. ");
Cout <"Enter three examples:/N ";
Cout <test1 <Endl;
Cout <Test2 <Endl;
Cout <test3 <Endl;
Wrong * wrong1 = new wrong (test1 );
Cout <* wrong1 <Endl;
Delete wrong1;
Cout <test1 <Endl; // There is no response on Dev-CPP.
Cout <"use the correct function:" <Endl;
Show_right (Test2 );
Cout <Test2 <Endl;
Cout <"incorrect function used:" <Endl;
Show_wrong (Test2 );
Cout <Test2 <Endl; // This piece of code has a serious error!
Wrong wrong2 (test3 );
Cout <"wrong2:" <wrong2 <Endl;
Wrong wrong3;
Wrong3 = test4;
Cout <"wrong3:" <wrong3 <Endl;
After the program ends, the Destructor is called. "<Endl;
Return 0;
}
Void show_right (const wrong &)
{
Cout <A <Endl;
}
Void show_wrong (const wrong)
{
Cout <A <Endl;
}
Running result:

Below are three examples:

The first example.
The second example.
The third example.

The first example.

This string will be deleted: the first example.

Use the correct function:
  
The second example.
The second example.

Use the wrong function:
The second example.

This string will be deleted: the second example.

This string will be deleted :? =
? =

Wrong2: The third example.
Wrong3: The fourth example.

The program ends and the Destructor is called.

This string will be deleted: The fourth example.

This string will be deleted: The third example.

This string will be deleted :? =

This string will be deleted: x =

This string will be deleted :? =

This string will be deleted:

Now, please try the running results on your own. It may be even worse! Next, I will analyze the reasons one by one.

First, you should know that the C ++ class has the following extremely important functions:

1. Copy the constructor.

Ii. Value assignment function.

Let's talk about copying constructors first. What is a replication constructor? For example, we can write the following code: Wrong test1 (Test2); this is initialization. We know that the initialization object should use constructors. But here? It should be said that the constructor is: Wrong (const wrong &); however, we have not defined this constructor? The answer is that C ++ provides the default copy constructor, and the problem lies here.

(1) When will the replication constructor be called? (Take the wrong class as an example .)

When we provide this code: Wrong test1 (Test2), it will be called. When the function parameter list is passed by value, that is, it does not use reference or pointer as the type, for example, void show_wrong (const wrong) is called. In fact, there are still some situations, but I will not list them here.

(2): What kind of function is it.

It is used to copy two classes. Take the wrong class as an example. The default replication constructor provided by C ++ is as follows:

Wrong (const wrong &)
{
STR = A. STR;
Len = A. Len;
}

In normal times, this will not cause any problems, but we have to talk about shortest replication and deep replication when we use the new operator and involve dynamic memory allocation. The above function is the implementation of the shortest copy, it just copies the pointer, and does not copy the data pointed to by the pointer, it is useless at all. For example! Just like a friend who asks you to send a program to him over the Internet, and you send the shortcut to him, what's the purpose? Let's talk about it in detail:

Assume that the string "C ++" is stored in object ". Its address is 2000. Now, we assign object A to object B: Wrong B =. Now, the STR pointers of objects a and B point to the 2000 address. It seems usable, but if the destructor of object B is called, the string "C ++" at Address 2000 has been erased from the memory, object A still points to address 2000. At this time, if we write this code: cout <A <Endl; or wait until the program ends, when the destructor of object A is called, can the data of object a be displayed? It will only be garbled. In addition, the program will do this: it uses two Delete operators for address 2000 consecutively. The consequence is very serious!

In this example, the following code is available:

Wrong * wrong1 = new wrong (test1 );
Cout <* wrong1 <Endl;
Delete wrong1;

Suppose that STR points to 2000 in test1, And the STR pointer in wrong points to 2000 in the same way. We deleted the data at 2000. What about the test1 object? It has been damaged. As you can see from the running results, when we use cout <test1, there is no response at all. When the destructor of test1 is called, it is displayed as follows: "This string will be deleted :".

Let's take a look at this Code:

Cout <"incorrect function used:" <Endl;
Show_wrong (Test2 );
Cout <Test2 <Endl; // This piece of code has a serious error!

The void show_wrong (const wrong a) parameter list of the show_wrong function is passed by value. Therefore, we execute the following code: Wrong A = Test2; the function has been executed, because of the lifecycle, object A is deleted by the destructor, and the error result is displayed immediately: This string will be deleted :? =. Of course, Test2 is also damaged. The solution is simple. Of course, you need to manually define a replication constructor! Human resources can win the day!

Wrong: Wrong (const wrong &)
{
Len = A. Len;
STR = new char (LEN + 1 );
Strcpy (STR, A. Str );
}

We perform deep replication. This function has the following functions: assume that the STR pointer in object A points to address 2000 and the content is "I am a C ++ boy !". When we execute the code wrong B = A, we first open a piece of memory, assuming 3000. We use the strcpy function to copy the content of Address 2000 to address 3000, and then point the STR pointer of object B to address 3000. In this way, we will not interfere with each other.

When we add this function to the program, the problem is solved in most cases, but it is not completely solved yet. The problem lies in the value assignment function. Our program has the following code:

Wrong wrong3;
Wrong3 = test4;

After my previous explanation, we should also find the root of this Code: Why can we do this: wrong3 = test4 ??? The reason is that C ++ provides such an operator overload function for your convenience: Operator =. So we can do this. We should have guessed that it also implements a shortest copy, with the same problem. For example, after the code is executed, the Destructor begins to show how powerful it is. Because these variables are post-in-first-out, the final wrong3 variable is deleted first: This string will be deleted: The fourth example. Normal. Finally, when test4 is deleted, the question is: this string will be deleted :? =. I don't need to go into details about the reason. I just want to write this assignment function. I still have some knowledge! For details, see:

In normal times, we can write such code: x = y = z. (All are Integer Variables .) In class objects, we also need this because it is very convenient. The object a = B = C is a. Operator = (B. Operator = (c )). The operator = function parameter list should be: const wrong & A, so it is not difficult for everyone to launch. to implement such a function, the return value should also be wrong &, in this way, a = B = C can be implemented. Let's start with writing:

Wrong & wrong: Operator = (const wrong &)
{
Delete [] STR; // delete data first
Len = A. Len;
STR = new char [Len + 1];
Strcpy (STR, A. Str); // copy the three actions
Return * This; // return your reference
}

Is that all right? If we have written this code: A = A, do you think we have deleted the data of object? This can be described as a series of errors. Therefore, we also need to check whether a value is assigned to ourselves. It is impossible to compare the data of only two objects, because the data of the two objects is likely to be the same. We should compare the addresses. The following are complete assignment functions:

Wrong & wrong: Operator = (const wrong &)
{
If (this = &)
Return * this;
Delete [] STR;
Len = A. Len;
STR = new char [Len + 1];
Strcpy (STR, A. Str );
Return * this;
}

After the code is added to the program, the problem is completely solved. The running result is as follows:

Below are three examples:

Example 1
Example 2
Example 3

Example 1

This string will be deleted: the first example.

Example 1

Use the correct function:

The second example.

The second example.

Use the wrong function:

The second example.

This string will be deleted: the second example.

The second example.

Wrong2: The third example.
Wrong3: The fourth example.

The program ends and the Destructor is called.

This string will be deleted: The fourth example.
This string will be deleted: The third example.
This string will be deleted: The fourth example.
This string will be deleted: The third example.
This string will be deleted: the second example.
This string will be deleted: the first example.

This article introduces the issue of dynamic memory allocation. I hope everyone can love programming and C ++!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.