New features in C++11

Keywords: Python C++ Algorithm


New features in C++11

Article catalog


1, Range based for loop

C++ 11 provides a special version of the for loop. In many cases, it can simplify the processing of arrays, which is the range based for loop.

When working with an array using a range based for loop, the loop can automatically iterate once for each element in the array. You don't have to use counter variables to control its iteration, and you don't have to worry about array subscript out of bounds.
The range based for loop uses a built-in variable called a range variable. Each time a range based for loop iterates, it copies the next array element to the range variable. For example, for the first loop iteration, the range variable will contain the value of element 0; In the second iteration of the loop, the range variable will contain the value of element 1, and so on

General format of range based for loops
 

for (dataType rangeVariable : array)    //Can be used with auto
       statement;

dataType: is the data type of the range variable. It must be the same as the data type of the array element, or the type that the array element can automatically convert. (you can use auto)
rangeVariable: is the name of the range variable. This variable will receive the values of different array elements during the loop iteration. During the first loop iteration, it receives the value of the first element; During the second loop iteration, it receives the value of the second element; and so on.
Array: is the name of the array to be processed by the loop. The loop iterates once for each element in the array.
Statement: is the statement to be executed during each iteration of the loop. To execute more statements in a loop, you can surround multiple statements with a set of braces.
For example
For example, suppose you have defined the following array:
int numbers[] = {1,3,5,7,9,2,4,6,8,10};
You can use a range based for loop to display the contents of the numbers array. The statement is as follows

for(int val : numbers)
{
    cout << "The next value is ";
    cout << val << endl;
}


Of course, you can also use the auto keyword. The code is as follows

for (auto val : numbers)
{
    cout << "The next value is ";
    cout << val << endl;
}

Use a range based for loop to modify the array

When a range based for loop is executed, its range variable will contain only a copy of an array element. Therefore, you cannot use a range based for loop to modify the contents of an array unless you declare a range variable as a reference.

To declare a scope variable as a reference variable, you can add a & symbol before the scope variable name in the loop header.

#include <iostream>
using namespace std;
int main ()
{
    const int SIZE = 5;
    int numbers[SIZE];
    //Get values for the array.
    for (int &val : numbers)
    {
        cout << "Enter an integer value: ";
        cin >> val;
    }
    // Display the values in the array.
    cout << "\nHere are the values you entered: \n";
    for (int val : numbers)
    {
        cout << val << " ";
    }
    cout << endl;
    return 0;
}

Note that the scope variable val has a & sign before its name, which means that it is declared as a reference variable. When the loop executes, the val variable will no longer be just a copy of the array element, but an alias of the element itself. Therefore, any changes made to the val variable will actually affect the array elements it currently references.

be careful

Usage condition of the scope for: the scope of the for loop iteration must be determined

2, C++11 perfect forwarding

Detailed explanation of C++11 perfect forwarding and implementation method (biancheng.net)

Talk about the perfect forwarding in C + + - Zhihu (zhihu.com)

What is C + + right value?

It is worth mentioning that the English abbreviation of the left value is "lvalue" and the English abbreviation of the right value is "rvalue". Many people think they are abbreviations of "left value" and "right value", but they are not. Lvalue is the abbreviation of "loader value", which can mean data stored in memory with explicit storage address (addressable), while rvalue is translated as "read value", which refers to data that can provide data value (not necessarily addressable, such as data stored in registers).

  •   The expression to the left of the assignment number (=) is an lvalue and the expression to the right is an lvalue
  • The named expression that can obtain the storage address is the lvalue; Otherwise, it is the right value.

C + + R-value reference

In C++98/03, & denotes a reference, but only lvalues are allowed to establish a reference

Adopted in C++11&&   Represents an R-value reference

int i=42;
int &r=i;   //Correct, r refers to i
int &&rr=i   //Error, cannot bind an R-value reference to an l-value
int &r2=i*42;  //Error, i*42 is an R-value
const int &r3=i*42;  //Correct, we can bind a const reference to an R-value
int &&r2=i*42; //Correct, bind rr2 to the multiplication result

Since an R-value reference can only be bound to a temporary object, we know that
1. The referenced object will be destroyed
2. There are no other users for this object

  You cannot bind an R-value reference directly to an l-value, but you can explicitly convert an l-value to the corresponding R-value reference type

int &&rr3 =std::move(rr1);  //rr1 is an lvalue
//A new standard library function called move is called to get the right value reference bound to the left value, which is defined in the header file utility.

  Perfect forwarding  

std::forward   The function is to keep the original value attribute unchanged.

Generally speaking, if the original value is an lvalue, it is still an lvalue after std::forward processing. If the original value is an lvalue, it is still an lvalue after std::forward processing.

Code example:

#include <iostream>

template<typename T>
void print(T & t){
    std::cout << "Lvalue" << std::endl;
}

template<typename T>
void print(T && t){
    std::cout << "Right value" << std::endl;
}

template<typename T>
void testForward(T && v){
    print(v);
    print(std::forward<T>(v));
    print(std::move(v));
}

int main(int argc, char * argv[])
{
    testForward(1);

    std::cout << "======================" << std::endl;

    int x = 1;
    testFoward(x);
}

Execution results:

Lvalue
 Right value
 Right value
=========================
Lvalue
 Lvalue
 Right value

//The first set of 1 passed in is an R-value, but after the function passes parameters, it becomes an l-value (space is allocated in memory)
//The second line uses the std::forward function and does not change its R-value attribute
//The third line uses the std::move function, which will forcibly convert the passed in parameters to right values.

//The second group of incoming x variables are lvalues, which must be lvalues after parameter transfer
//The second line uses the std::forward function and still maintains the left value
//The third line uses the std::move function to cast it to an R-value


3, lambda expression

Lambda expressions in C++ 11 are used to define and create anonymous function objects to simplify programming.
The syntax of Lambda is as follows:

[capture list] (params list) mutable exception-> return type { function body }

The specific meanings of each item are as follows:

  1. capture list: capture a list of external variables
  2. params list: parameter list
  3. mutable indicator: used to indicate whether the captured variable can be modified
  4. Exception: exception setting
  5. Return type: return type
  6. Function body: function body
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

bool cmp(int a, int b)
{
    return  a < b;
}

int main()
{
    vector<int> myvec{ 3, 2, 5, 7, 3, 2 };
    vector<int> lbvec(myvec);

    sort(myvec.begin(), myvec.end(), cmp); // Old practice
    cout << "predicate function:" << endl;
    for (int it : myvec)
        cout << it << ' ';
    cout << endl;

    sort(lbvec.begin(), lbvec.end(), [](int a, int b) -> bool { return a < b; });   // Lambda expression
    cout << "lambda expression:" << endl;
    for (int it : lbvec)
        cout << it << ' ';
}

 C++11 Lambda expression - dishuiwa blog park a highlight of C++11 is the introduction of Lambda expression. Using Lambda expressions, anonymous functions can be easily defined and created. For C + +, the concepts of "Lambda expression" or "anonymous function" sound profound, but manyhttps://www.cnblogs.com/DswCnblog/p/5629165.html

Lambda expression in C + + - paradise at the end of the season - blog Garden 1. Overview lambda expression in C++ 11 is used to define and create anonymous function objects to simplify programming. The syntax of lambda is as follows: you can see that lambda is mainly divided into five parts: [function object parameters] and (operators)https://www.cnblogs.com/jimodetiantang/p/9016826.html 

4, Smart pointer

Smart pointer is a class used to store pointers to dynamically allocated objects. It is responsible for automatically releasing dynamically allocated objects and preventing heap memory leakage. Dynamically allocated resources are managed by a class object. When the class object declaration cycle ends, the destructor is automatically called to release resources

  Function of smart pointer: smart pointer can help us avoid memory leakage caused by forgetting to release after applying for space;

shared_ptr       Reference counting smart pointer

As the name suggests, reference count is to record how many smart pointers are referenced in memory. Add a reference count plus one, and the expired reference count minus one. When the reference count is 0, the smart pointer will release resources;

After reading this article, don't say you can't use smart pointers

Posted by AustinP on Sat, 25 Sep 2021 10:43:14 -0700