Temporary variables in C ++

Source: Internet
Author: User

They are children abandoned by God. No one has ever seen them, and no one knows their names. They are destined to wander between the towering cliff on the edge of fate and the deep abyss,

Use your own short life to smooth the gap between life and death. for example, it is invisible to the sun. it's time to create a monument for them. The Tomb inscription says: I'm coming, I'm leaving, I'm happy.

Many people's understanding of temporary variables is limited:

String temp;

In fact, from the perspective of C ++, this is not a temporary variable, but a local variable.

The temporary variables of C ++ are the temporary variables automatically generated by the compiler when needed. They are notCodeBut they exist in the binary code generated by the compiler,

Also create and destroy. in C ++, the problem of temporary variables is particularly important, because each temporary variable of the User-Defined type must start with the User-Defined constructor and destructor (if the user provides)

It's a damn compiler! Someone should complain that the compiler is always doing something secretly behind itself, but if we leave the compiler's work, we may be unable to do anything.

If X is a user-defined type with default constructor, copy constructor, assign values, and destructor (these are also the four basic functions of the class ), consider the following code:

 
X get (x Arg) {return ARG;} x a; x B = get ();

Even such simple code is hard to implement.

Let's analyze what happened during code execution?

First, I want to tell you a secret: for a function, it is impossible to pass in an object or send out an object.

It is easy to let a Function Pass in or out a built-in data type, such as int, but it is very difficult for the user to customize the type of the object, because the compiler must look for these objects

Write constructor and destructor, either inside or outside the function, unless you skip these difficulties with pointers or references.

So what should we do? Here, the compiler must play some necessary tricks. Well, the key is the temporary variable.

For functions that take objects as parameters:

 
Void Foo (x X0) {}x xx; Foo (XX );

The compiler generally converts one of the following two conversion methods:

1. Provide temporary variables outside the Function

 
Void Foo (X & X0) // modify the foo declaration to reference {} X xx; // declare XXX: X (XX ); // call the default constructor X _ temp0 of XX; // declare the Temporary Variable _ temp0x: X (_ temp0, XX ); // call the _ temp0 copy constructor Foo (_ temp0); // call foox ::~ X (_ temp0); // call the destructor of _ temp0 X ::~ X (XX); // call the destructor of xx

2. Provide temporary variables in the function

 
Void Foo (X & X0) // modify the foo declaration to reference {X _ temp0; // declare the Temporary Variable _ temp0 X: X (_ temp0, x0); // call the copy constructor of _ temp0 X ::~ X (_ temp0); // call the destructor of _ temp0} X xx; // declare XXX: X (XX ); // call the default constructor Foo (XX) of XX; // call foox ::~ X (XX); // call the destructor of xx

Both declaring temporary variables inside the function and declaring temporary variables outside the function are similar. The meaning here is that since the parameter must be passed

The semantics of the input function, that is, the real parameter XX cannot be modified, so we will use a temporary variable like a touch to complete the semantics of this value.

However, this is not without a cost. The compiler must modify the declaration of a function, change the object to an object reference, and modify all function calls. The cost is indeed huge,

However, this is just an unhappy compiler,ProgramPersonnel and program execution efficiency is not affected

For functions that return values with objects:

 
X Foo () {x xx; return xx;} x yy = Foo ();

The compiler generally performs the conversion as follows:

 
Void Foo (X & _ temp0) // modify the foo declaration to reference {x xx; // declare xx x: X (XX ); // call the default constructor of XX _ temp0: X (XX); // call the copy constructor of _ temp0 X ::~ X (XX); // call the destructor of XX} x yy; // declare yyx _ temp0; // declare the Temporary Variable _ temp0foo (_ temp0 ); // call foox: X (YY, _ temp0); // call the copy constructor X: ~ of YY ::~ X (_ temp0); // call the destructor of _ temp0 X ::~ X (yy); // call the destructor of YY

Since we have already declared YY, why do we need to declare _ temp0? Actually, here we can combine YY and temporary variables.

After optimization, the above Code looks like this:

 
Void Foo (X & _ temp0) // modify the foo declaration to reference {x xx; // declare xx x: X (XX ); // call the default constructor of XX _ temp0: X (XX); // call the copy constructor of _ temp0 X ::~ X (XX); // call the destructor of XX} x yy; // declare yyfoo (yy); // call foox ::~ X (yy); // call the destructor of YY

Well, how can this be considered an optimization?AlgorithmActually, these skills are already very common and have a special name named return value (nrv) for optimization.

Nrv optimization is now regarded as an unshirkable optimization operation of the Standard C ++ Compiler (although its demand actually exceeded the formal standard)

Besides taking the class as the parameter, if the parameter type is const T & type, this may also cause temporary variables

 
Void fun (const string & Str) const char * name = "WGS"; fun (name );

Well, do you still remember the description in the const document? For this special parameter type, the compiler is happy to perform automatic conversion for you. The cost is a temporary variable,

However, if you do it yourself, you can only declare one local variable.

Why are functions and temporary variables so correlated? The root cause is the semantics of the object's value passing. This is also why C ++ encourages the passing of object addresses.

Similar to functions, there is also a main type of condition that is the pleasure of temporary variables, that is, expressions.

 
String S, T; printf ("% s", S + t );

Where should the S + T result be stored? Only temporary variables.

This printf statement brings about a new problem, that is, what is the "Life Cycle of temporary variables?

As we can see from the situation of functions, temporary variables are analyzed as early as possible after the mission of exchanging content. What about expressions?

If the structure is analyzed after S + T calculation, the print function prints an invalid content. Therefore, the C ++ rule is as follows:

The temporary variable should be parsed at the last step of the "full expression" evaluation process that causes the temporary variable to be created

What is a "complete expression "? Simply put, it is not a subexpression of an expression.

This rule sounds simple, but it is very troublesome to implement it. For example:

 
X Foo (int n) if (FOO (1) | Foo (2) | Foo (3 ))

X contains operator int () conversion, so it can be used in the IF statement.

Here Foo (1) will generate a temporary variable 1, if this part is divided into false, Foo (2) will continue to generate a temporary variable, if this part is also false, foo (3 )...

The parameters of a temporary variable are related to the runtime, even worse, remember that you actually generated several temporary variables and analyzed the structure at the end of the expression to maintain the consistency between the object structure and the structure.

I guess it will be a complicated piece of code, and more if judgments can be added to solve the problem. Well, I am not a compiler.

The above rules actually have two exceptions:

 
String S, T; string v = 1? S + T: S-t;

What is the complete expression here? Statement, but after the complete expression ends, the temporary variable cannot be destroyed immediately, but must be destroyed only after the variable V value is assigned. This is the exception rule 1:

Any temporary variables that contain the expression execution result should be stored until the object is destroyed after initialization.

 
String S, T; string & V = S + T

Here, the temporary variables generated by S + t cannot be destroyed even after the value assignment of variable V, otherwise the reference will be useless. This is exception rule 2:

If a temporary variable is bound to a reference, the temporary variable should be reserved for this temporary variable and the referenced variable must be exceeded the scope of the variable before being destroyed.

This articleArticleIt may be somewhat esoteric. After all, most of the content comes from <inside the C ++ object model>

Leave a piece of advice:

In STL, the following code is incorrect.

 
String getname (); char * ptemp = getname (). c_str ();

Getname returns a temporary variable. After assigning the internal char pointer to ptemp, the structure is parsed. In this case, ptemp is an invalid address.

It is true that, as Bjarne stroustrup, the inventor of C ++, said, this usually happens when different types of conversions occur.

In QT, similar code is as follows:

 
Qstring getname (); char * ptemp = getname (). toascii (). Data ();

Ptemp is an invalid address.

I hope you will not make similar mistakes.

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.