Do not return a reference to a local object or a reference to a pointer initialized with new in the function.

Source: Internet
Author: User

These terms may sound complicated, but they are not. It's just a simple truth. Believe me.

First, let's look at the first case: return a reference to a local object. The problem is that the local object-as the name suggests-is only local. That is to say, a local object is created when it is defined and destroyed when it leaves the lifecycle. The so-called life space refers to the function bodies where they are located. When the function returns, the control of the program leaves the space, so all local objects in the function are automatically destroyed. Therefore, if a local object reference is returned, the local object is actually destroyed before the function caller uses it.

This problem occurs when you want to improve the program efficiency and make the function result return through reference rather than value. The following example is the same as in Clause 23. The purpose is to explain in detail when to return a reference and when not:

Class rational {// a rational number class
Public:
Rational (INT Numerator = 0, int Denominator = 1 );
~ Rational ();

...

PRIVATE:
Int N, D; // numerator and denominator

// Note that operator * (incorrect) returns a reference
Friend const rational & operator * (const rational & LHS,
Const rational & RHs );
};

// Operator * incorrect implementation
Inline const rational & operator * (const rational & LHS,
Const rational & RHs)
{
Rational result (LHS. N * RHS. N, LHS. D * RHS. D );
Return result;
}

Here, the result of a local object is created when it enters the operator * function body. However, all local objects will be automatically destroyed when they leave the space they are in. In this example, the result leaves the space where the return statement is executed. Therefore, if you write:

Rational two = 2;

Rational four = two * Two; // same as operator * (two, two)

The following events will occur during function calling:

1. partial object result is created.
2. initialize a reference to make it another name of the result. This reference is placed on the other side first and left as the return value of operator.
3. The result of a local object is destroyed, and the space occupied by the stack can be used by other parts of the program or other programs.
4. Use the reference in step 2 to initialize the Object four.

Everything is normal. It was not until step 2 that an error was generated. In the words of the high-tech industry, a huge mistake was generated ". Because the reference initialized in step 1 points to no longer a valid object at the end of step 2, the initialization result of the Object four is completely uncertain.

The lesson is obvious: Do not return a reference to a local object.

"Well," you may say, "isn't the problem that the object to be used leaves its space too early? I can solve it. Do not use local objects. You can use new to solve this problem. "As follows:

// Another incorrect implementation of operator *
Inline const rational & operator * (const rational & LHS,
Const rational & RHs)
{
// Create a new object on the heap
Rational * result =
New Rational (LHS. N * RHS. N, LHS. D * RHS. D );

// Return it
Return * result;
}

This method does avoid the problems in the above example, but it raises new difficulties. As we all know, to avoid Memory leakage in the program, we must ensure that delete is called for each pointer generated with new. However, the problem here is that for the new function, who will call the corresponding delete?

Obviously, the caller of operator * is responsible for calling Delete. Is it true? Unfortunately, even if you write it as a rule in black and white, the problem cannot be solved. The reason for making such a pessimistic judgment is based on two reasons:

First, we all know that programmers are very careless. This does not mean that you are careless or I am careless, but that no programmer does not deal with a person with such habits. To make such a programmer remember how likely it will be to get a result pointer and call delete whenever operator * is called? Also, they must use operator * as follows *:

Const rational & four = two * Two; // get the discarded pointer;
// Store it in a reference
...

Delete & four; // get the pointer and delete it

This probability will be much smaller. Remember, as long as a caller of an operator * forgets this rule, memory leakage will occur.

Returning discarded pointers has another more serious problem that can be avoided by even the most conscientious programmers. In this case, operator * is used only for the intermediate value. It is only used to calculate a larger expression. For example:

Rational one (1), two (2), three (3), four (4 );
Rational product;

Product = one * Two * Three * four;

The product calculation expression needs to be called by three independent operator *. rewriting the expression in the corresponding function form will make it clearer:

Product = Operator * (operator * (ONE, TWO), three), four );

Yes, the objects returned by each operator * call must be deleted, but delete cannot be called here, because no returned object is saved.

The only solution to this problem is to write code like this:

Const rational & temp1 = one * Two;
Const rational & temp2 = temp1 * three;
Const rational & temp3 = temp2 * four;

Delete & temp1;
Delete & temp2;
Delete & temp3;

If so, the best result you can expect is that people will ignore you. To be more practical, you may spend days with your fingers or be sentenced to ten years of hard work writing microcode for Wafer cookers or toaster.

So remember your lesson: writing a function that returns discarded pointers is tantamount to waiting for Memory leakage.

In addition, if you think you have come up with a solution to avoid the uncertain behavior caused by "returning a local object reference" and "Heap) the memory leakage caused by the reference of the allocated object ", so please go to clause 23 to see why the reference to the returned local static object will not work properly. After reading it, it may help you avoid headaches and medical troubles.

 

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.