Value Type from C ++ Return Value Optimization (RVO) to C #

zhaozj2021-02-16  59

Value Type from C Return Value Optimization (RVO) to C #

First look at a simple C code:

TYPE GET (INT i) {

Return Type (i);

}

TYPE T = GET (1);

Here, we look from the basic semantics of C , it should be Type (i) calls a copy constructor, generate a temporary object in the stack; then use the object to construct the object; then call the sectual object; In the caller, call the copy constructor with the returned temporary object to initialize the object T. The destructor of the object is returned later, the function returns the previous call.

So, Type T = Get (i); there should be three copy constructor and the call of two destructuring functions.

However, there is a saying that the compiler may optimize the two temporary objects, and the final optimization result will be only one constructor. Because it is obvious that we are actually just a Type object with an integer.

Well. It seems to be very reasonable!

So, which kind is right? There was no voice without investigation, so I did experiment with VC 6.0. Put some cout << .... In the copy constructor, observe the results of printing, the result is consistent with my Simple, Naïve's forecast. Three copy constructor, two destructor.

"You a mentally smart compiler! Is your head into the water?" (Forgot the compiler without your head) "It is obvious that my two temporary objects in this example are not used!"

So, go online, check the information, google!

Here is some of the results I have found:

In fact, this optimization of this value transfer is not limited to the return value. For the following example:

Void f (t t) {}

Void main () {

T T1;

f (t1);

}

There is also this consideration.

f (t) is passed by value. A copy should be made in semantics such that the change in the function of the function does not affect the original T1.

However, because we did not use T1 after calling F (T1), it may be optimized to the copy, use T1 directly? This saves a copy constructor and a destructor.

However, whether it is an optimization of the return value or the optimization of the topic object above, in 1995, it is strictly restricted by the Standards before the introduction of C new standards (although some compilers do not follow this standard, or Supports this "optimization")

So, why?

This involves a common concern for Side-Effect.

What is Side-Effect?

The so-called Side-Effect is a function of a function that can be distinguished from the status of the system.

Int Add (int i, int j) {RETURN I J;} is not Side-Effect,

Void set (int * p, int = tent v) {p [i] = v;} is Side-Effect. Because it changes the value of an array element, this array element is visible outside of the function.

In a general sense, all optimization should be performed on the basis of observational behavior that does not affect the program. Otherwise, it is fast, but the result is completely different!

And the C copy constructor and the destructive function are still Side-Effect. If our "optimization" removes a copy constructor with Side-Effect and a destructive function, this "optimization" is likely to change the observable behavior of the program. (Note, I am talking about "possibly", because "negative negative", two modes with Side-Effect function, may not affect the program's observable behavior without considering parallel operation However, this Sethon lost horse, the compiler is difficult to judge) Based on this concern, the 1995 standards explicitly prohibit optimization of copy constructor and secting functions containing SIDE-EFFECT. At the same time, there are some proposals for C expansion, consider making programmers to allow the optimization of the class. Programmers can clearly tell the compiler: Yes, I copy constructor, the destructor is Side-Effect, but you don't work, despite the optimization, there is something!

Hey, Side-Effect is a thing that makes people hate and love! It makes it difficult to optimize the compiler; increase the difficulty of program maintenance and debugging. Therefore, Functional Language is the same as the flood beast as a flood beast. But at the same time, we are hard to leave Side-Effect. Do not say that programmers are more accustomed to the imperative programming method, like database operations, IO operations are naturally Side-Effect.

However, individuals still think that the C standard is reasonable to "optimize" conservative attitude. In any case, let "optimize" can potentially secretly change the behavior of the program, it is always uncomfortable.

However, the contradiction is a confrontation. (I want to have more than 80 points that year.). The "optimized" of this aggressive is a wave of waves. A small snacky molecule headed by Stan Lippeman has never stopped from the standard subversive and peaceful conspiracy. Isn't this? In the 1996, a wind and rain, a sinless C new standard draft. In this draft, a relaxation of the RVO (Return Value Optimization) has joined the optimization limit, and the capitalist road will be given to the capitalist. The specific content is to say: Allow the compiler to optimize the return of the named local object, even if the copy constructor / destructor is Side-Effect, there is no heliscence. The thought hidden behind this proposal is: in order to improve efficiency, rather to change the risk of changing program behavior. Ning wants the capitalist seedlings, don't socialist grass!

I think this kind of crime proposal is actually submitted, it should be because the semantic efficiency of C is really too "mother". When you write a Complex Operator (Const Complex & C1, Const Complex & C2);, you need to call several copy constructor and destructor! Comrades! (Painfully, speaking, weighing the Yangtze Rice) How to reflect the superiority of socialist production relations?

Next, when I want Google C 's latest standard, I can't find anything RVO is finally adopted. Go to ANSI's website, actually pay for the Download document. "Laozi will not pay at the museum in the city, how many bad documents will be given ?!"

The story has no end, it is really unhappy. I don't know if the standard has not been finalized, so VC 6 is not optimized, or the VC is not fully complied with standards. However, it is certain that it is certain. When writing the program, it is best not to rely on RVO (someone, like Stan Lippeman, also called NRV optimization). Because, regardless of whether the debate on the standard has been a result, it is actually the implementation of each compiler is still the government, and there is no unity. A guy called Scott Meyers (forgot what to sell), if your program depends on RVO, it is best to remove this dependence. That is, you still can't use it regardless of the RVO to the end standard. Not only cannot be used, but it has to be alert to the changes in procedures that RVO may bring. (I don't know if this guy is busy for a long time!)

When I said, I remembered a problem that I had a confused me for a long time. I don't understand why C # does not allow the value type function to define the value type.

Here, you will be briefly introduced to the Value Type in the C #.

Value_type in C # is like a value, always only COPY, value. Therefore, it will always be in-place. If you put a Value Type's data in an object, its life is the same as that object; if you declare a Value Type variable in the function, its life is in Lexical Scope.

{

The_valueType Value;

} // Value is here to die

Ah! Is this not the C Stack Object of our miss?

In C , auto_ptr, shared_ptr, and containers are not all used to manage resources with destructive functions?

C #, Java Although uses Garbage Collection technology to collect useless objects, we don't have to worry about memory recycling. However, Garbage Collection does not guarantee that useless objects must be collected, and does not guarantee that the Dispose () function must be called, and it is not guaranteed when an object is reclaimed. So for some non-memory resources, like database connections, network connectivity, we still hope to have something similar to Smart Pointer to help us manage. (Try-finally can be used, but because it affects Lexical Scope, sometimes it is not so convenient)

So, I am full of deeper class hatred for C # canceling Value Type.

However, now I want to come, this design of C # must be punished by C failed:

Value Type has no copy constructor. C # only by default Copy, no Side-Effect

Value Type is not allowed to have a destructor. C # has Garbage Collection, the only use of the destructor only Will be some Side-Effect icon to turn off the database connection. Therefore, the destructor is canceled, and the Side-Effect of Value Type is canceled.

Without Side-Effect, the system can be optimized arbitrarily.

For the following procedures:

THE_VALUETYPE GET (INT I) {Return The_ValueType (i);

THE_VALUETYPE T = Get (1);

转载请注明原文地址:https://www.9cbs.com/read-26052.html

New Post(0)