[C++11] initializer_list | rvalue reference | move construction | perfect forwarding

1. Uniform list initialization

{ } initialization

C++11 expands the scope of use of the parenthesized list (initialization list) so that it can be used for all built-in types and user-defined types. Using the initialization list, you can add an equal sign (=) or
not

Assigning 1 to x1 and omitting the assignment symbol at x2, assigning 5 to x2
can also open up 4 int spaces for new and initialize them to 0


When creating an object, you can use the list initialization method to call the constructor initialization, or you can omit the equal sign

initializer_list

The constant array inside curly braces, C++ can recognize it as a type initializer_list,
the initializer_list class has template parameters, because the passed int data, so it is initializer_list


There are two pointers size in the class
as the subtraction of two pointers
begin points to the beginning position, end points to the next end position


The data cannot be modified, indicating that
any constant array in the constant area can be assigned to the object of initializer_list


insert image description here

The vector in C++11 is initialized by using initializer_list through the new constructor

2. Quote

lvalue reference

An lvalue reference is to give an alias to an lvalue.
An lvalue is an expression of data (such as a variable name or a reference pointer)
whose address can be obtained as an lvalue.


The lvalue appears to the left of the assignment symbol (it can also appear to the right)


rvalue reference

An rvalue is also an expression representing data (such as literal constants, expression return values, and function return values).
Rvalues ​​can appear on the right side of assignment symbols, but cannot appear on the left side of assignment symbols. Rvalues ​​cannot take addresses

An rvalue reference is an alias to an rvalue


Conversion between lvalue references and rvalue references

As x+y is an rvalue, an lvalue reference cannot directly refer to an rvalue,
but it can be converted by implicit type. Since the temporary variable is constant, just add const


a is used as an lvalue, and an rvalue reference cannot directly refer to an lvalue. After using move, its return value is used as an rvalue

Real usage scenarios of rvalue references

Although const can be added to lvalues, both lvalues ​​and rvalues ​​can be used,
but it is impossible to distinguish whether it is an lvalue or an rvalue


After adding rvalue references, in the process of parameter passing, better parameter matching
can distinguish whether to call lvalue references or rvalue references


mobile structure

There are two types of rvalues:
1. Pure rvalue (built-in type)
2. Xvalue (custom type)


s1 is used as an lvalue, call the copy construction
s1+s2 as the return value of the expression, which means that the rvalue is about to be xvalue


If the rvalue is deeply copied (create another space to copy the original data, and then release the original space), it is
unnecessary to copy the xvalue, and the cost is too high


insert image description here
Because of const, whether it is an lvalue or an rvalue can be passed as a parameter


After transferring the resources of rvalue (xvalue) ret2
uses rvalue references to distinguish rvalues, there is no need to perform deep copy, and the
copy that receives rvalue as a parameter is called moving copy


insert image description here
Call the move constructor to make a move copy


insert image description here
The rvalue no longer calls deep copy, but uses mobile copy

C++98 and C++11 value return problem

insert image description here
For return by value, C++98 will perform two copy constructions at the beginning, and
after the compiler optimizes, it will perform one copy construction


insert image description here

When the compiler does not optimize,
str is an lvalue as a temporary variable. Passing str to a temporary variable is a copy construction. The
temporary object is invisible and cannot be know its address, so it is an rvalue (will be an xvalue),
so the right The value is passed to str, which belongs to the move construction

When the compiler optimizes,
the compiler will find a way to identify the temporary variable str in the function as an rvalue (use move to return the value of the function as an rvalue), and perform move construction (resource transfer)


insert image description here
s2 carries out deep copy, copies the data of s1 to the newly opened space
after move(s1), the return value of the expression is used as the rvalue
s3 for mobile copy, and the resources of s1 are transferred to s3, so s1 is empty

Precautions

The address of the rvalue cannot be taken, but after the alias is given to the rvalue, the rvalue will be stored in a specific location, and the address of the location can be taken. For example: the address of the literal constant 10 cannot be taken, but after the ret reference, it can
be You can also modify ret to take the address of ret. If ret cannot be modified, you need to add const, that is, const int &&

Summarize

Lvalue references reduce copying and improve efficiency . Rvalue references also reduce copying and improve
efficiency. Value, no deep copy, direct mobile copy (resource transfer), improve efficiency



3. Perfect forwarding

Write a function that accepts whether the passed parameter is an lvalue or an rvalue (after the lvalue is moved, the return value is an rvalue)

When an lvalue is used as a parameter, reference folding will occur and fun(t) will be called. At this time, t is an lvalue, so an lvalue reference will be output


When an rvalue is used as a parameter, in fact, after the rvalue is received, it needs to be moved and copied. After the rvalue is referenced, the attribute will become an lvalue, otherwise the resource transfer cannot be performed.


Call push_back, the parameter is an rvalue, and the attribute will become an lvalue after the rvalue reference is referenced, but it becomes an lvalue for resource transfer, before the transfer,
call insert first during this period, (x is used as an lvalue) , calling insert on an lvalue reference will result in a deep copy instead of a move copy


C++ supports perfect forwarding, which is used to maintain the original attributes and avoid the situation that the parameter x is transferred too early before the resource transfer


So when the fun parameter is added to forward for perfect forwarding, after making the rvalue reference, it does not immediately become an lvalue, but keeps the original attribute rvalue, so
call the corresponding fun to print the rvalue reference

Guess you like

Origin blog.csdn.net/qq_62939852/article/details/131125137