Testing my understanding of function return

As a newbie, I found a rather cryptic explanation for returning from a function in C ++ books.

Here is a brief overview of my understanding, hope someone can fix it:

Premises:

T foo() { ... return expr; } main() { T var = foo(); } 

Is my understanding of the return process understood correctly?

  • The result of evaluating expr implicitly converted to the return type of the function T This conversion happens inside foo ();
  • The converted value above is used to initialize a temporary object, such as "x". Sub-Question: does this second conversion happen inside foo () or main ()?
  • The temporary object "x" is used to initialize the var variable in main ().

Any input is welcome!

+6
source share
3 answers

We approach this systematically.

If the function is declared as T f(); , and T not void , and if the function returns normally, then it should be returned through the form instruction return e; where e is some expression.

When you evaluate the expression of the expression function f() , you get a value. Suppose U denotes an object type. If T = U & or T = U && , then the value is of type U , the expression e must be able to bind to the link, and the return value is the value of e . (The return value is also the so-called "glvalue", in terms of its category of values). In this case, nothing else happens. The function call value is the returned thing.

However, when T = U , then the value of f() is the so-called "prvalue" ("pure rvalue"), and this requires the creation of a temporary object of type U This object is constructed as if U obj = e (i.e. implicitly converted from e ). The value of f() is this temporary object. It can be used either to initialize another object (for example, U x = f(); ), or it can be attached to a link (for example, U && r = f(); ).

The binding of the returned expression e to the value of the call function occurs as the last thing inside the area of ​​the function body. It is noteworthy that this is until the end of the region, that is, before the object objects are destroyed. For example, if an exception occurs when constructing the return value object, the region must expand to destroy local objects before the exception enters the call area. Another useful illustration could be the use of secure security devices, for example. mutex locks:

 U f() { std::locK_guard<std::mutex> lock(state_mutex); return state.get_value(); } 

Here we assume that the initialization is U obj = state.get_value(); makes sense, and we further assume that state.get_value() should only be called when state_mutex locked. The above code does this correctly and briefly.

+6
source
  • You are right, implicit conversion occurs within foo . Consider when you have more than one return , and each returns a different type - all of these types must be converted before the value can be returned.
  • There is no second conversion. The first transformation takes place as part of a construction or temporary assignment.
  • Correct, except as described below.

There will be an optimization that many compilers will make called copy elision , which skips the temporary in general.

+4
source

Your understanding is basically correct.
There may be some optimizations, so there are not many steps to copy. It can be either in the form of return value optimization , or in C ++ 11 move semantics

Regarding your additional question;
You should make an assumption not , for example, custom conversion operators, constructors
destructors, etc.

+2
source

Source: https://habr.com/ru/post/971677/


All Articles