Clause 22: Try to use "Pass reference" instead of "pass value"

Source: Internet
Author: User

C LanguageC ++ inherits this tradition and uses it as the default method. Unless explicitly specified, the function parameters always pass
"Copy of real parameters" for initialization. The caller of the function also obtains the copy of the function return value.
As I pointed out in the introduction of this book, the specific meaning of "passing an object by value" is defined by the copy constructor of the class of this object. This causes
It becomes a very expensive operation. For example, let's look at the structure of the (just hypothetical) class below:

Code

Class Person {
Public :
Person (); // Parameters are omitted for simplicity.
//
~ Person ();
...
Private :
String Name, address;
};
Class Student: Public Person {
Public :
Student (); // Parameters are omitted for simplicity.
//
~ Student ();
...
Private :
String Schoolname, schooladdress;
};

 

Now we define a simple function returnstudent, which takes a student parameter (via value) and returns it immediately (also via value ). Call
Functions:
Student returnstudent (student s) {return s ;}
Student Plato; // Plato (Plato) in
// Socrates (Socrates)
Returnstudent (Plato); // call returnstudent
In this seemingly irrelevant function call process, what exactly does it happen internally?
To put it simply, student's copy constructor is called to initialize s to Plato, and student's copy constructor is called
The return value object is initialized to S. Then, the destructor of S is called. Finally, the destructor of the returned object of returnstudent is called. So, what?
The cost of a function that has not been done is that the copy constructor of two student plus two student constructor.
But it's not over! The student object has two string objects, so each time you construct a student object, you must also construct two string objects. Student object
It is inherited from the person object, so a person object must be constructed every time a student object is constructed. One person object has two other objects.
So the construction of each person must be accompanied by the construction of the other two strings. Therefore, passing a student object through the value will eventually cause the call.
One student copy constructor, one person copy constructor, and four string copy constructor. When the student object is destroyed, each constructor pair
Call a destructor. Therefore, the final overhead of passing a student object through values is six constructor and six destructor. Because
The returnstudent function uses two values (one pair of parameters and one pair of return values). This function calls a total of twelve constructors and twelve destructor.
Count!
In the eyes of C ++ compiler designers, this is the worst case. The compiler can be used to eliminate some calls to the copy constructor (C ++ standard-see the Terms and Conditions.
50 -- describes the specific conditions under which the compiler can perform such optimization, and the M20 provides an example ). Some compilers also do this. However
When this is common in all compilers, be cautious about the overhead caused by passing objects through values.
To avoid this potentially expensive overhead, instead of passing objects through values, you must reference them:
Const student & returnstudent (const student & S)
{Return s ;}
This is highly efficient: No constructor or destructor is called because no new object is created.
Passing parameters through references has another advantage: it avoids the so-called "slicing problem )". When the object of a derived class acts as the base class
When an object is passed, its (derived class Object) behavior as a derived class will be "cut" and become a simple base class object. This
It is often not what you want. For example, assume that the following class is designed to implement the graphic Window System:

Class Window {
Public :
String Name () Const ; // Return window name
Virtual   Void Display () Const ; // Draw window content
};
Class Required wwithscrollbars: Public Window {
Public :
Virtual   Void Display () Const ;
};

 

Each window object has a name, which can be obtained through the name function. Each window can be displayed and can be implemented by calling the display function.
The display declaration is virtual, which means that a simple window-based Class Object is displayed in a way that is often the same as a very expensive javaswwithscrollbars object.
(For details, see section 36, 37, and M33 ).
Now let's assume that we write a function to print the window name and then display the window. The following is a function written in the wrong way:
// A function troubled by the cutting problem
Void printnameanddisplay (window W)
{
Cout <W. Name ();
W. Display ();
}
Imagine what will happen when you call this function using a javaswwithscrollbars object:
Descriwwithscrollbars wwsb;
Printnameanddisplay (wwsb );
Parameter W will be created as a Windows Object (it is passed by value, remember ?), All actions of wwsb
The behavior characteristics of the windowwithscrollbars object are all "cut. Inside printnameanddisplay, W acts like a window-like object.
(Because it is a window object), regardless of the type of the object that was originally uploaded to the function. In particular, the printnameanddisplay internal
The call to display is always window: Display, rather than wide wwithscrollbars: display.
The Method to Solve the cutting problem is to pass W through reference:
// A function that is not troubled by the "cutting problem"
Void printnameanddisplay (const window & W)
{
Cout <W. Name ();
W. Display ();
}
Now w's behavior is consistent with the actual type of the function to be uploaded. In order to emphasize that w cannot be modified within the function although it is passed by reference, it is necessary to adopt the establishment of Clause 21
Declare it as Const.
Transferring references is a good practice, but it will lead to its own complexity. The biggest problem is the alias problem, which is discussed in Clause 17. In addition
It is important that sometimes references cannot be used to transmit objects. For more information, see section 23. In the end, references are almost implemented through pointers.
The pass object is actually a pass pointer. Therefore, if a small object, such as int, is used to pass a value, it is more efficient than transferring a reference.

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.