[C++11] Lvalue reference and rvalue reference


  Table of contents

1. New class functions

1. New default member functions

2. Class member variable initialization

3. The keyword default that forces the default function to be generated

4. It is forbidden to generate the keyword delete of the default function

Two, lvalue and rvalue

1. Lvalue and lvalue reference

2. Rvalues ​​and rvalue references

2.1 The alias of rvalue is lvalue

2.2 Universal reference for templates

2.3 Perfect forwarding

3. The usage scenarios and meanings of lvalue references and rvalue references

3.1 Usage scenarios of lvalue references

3.2 Usage scenarios of rvalue references

3. "Git from entry to proficiency"


1. New class functions

1. New default member functions

C++11 adds default member functions of two classes: move constructor and move assignment operator overloading.

If you do not manually implement the move constructor, and the destructor, copy construction, and assignment operator overloading are not manually implemented, the compiler will generate a default move constructor for you. The move constructor generated by default copies the value of the built-in type by byte. For the custom type, its move constructor will be called. If the built-in type does not have a move constructor, the compiler will call its copy constructor.

If you do not manually implement the overloading of the move assignment operator, and the destructor, copy construction, and assignment operator overloading are not manually implemented, the compiler will generate a default move assignment operator overload for you. The overloaded move assignment operator generated by default copies the value of the built-in type by byte. For the custom type, it will call its overloaded move assignment operator. If the built-in type does not have an overloaded move assignment operator, the compiler will go to Call its assignment operator overload.

2. Class member variable initialization

C++11 allows initial default values ​​​​for member variables at class definition time, and the default generation constructor will be initialized with these default values.

3. The keyword default that forces the default function to be generated

Person(Person&& p)=default;//让编译器强制生成移动构造

4. It is forbidden to generate the keyword delete of the default function

For example, now it is necessary to disable the copy constructor of a certain class. The C++98 method is to add private permissions to the copy constructor of this class, and only declare that it is not implemented, so that the copy constructor can be disabled inside and outside the class.

C++11 uses the delete keyword to prohibit the generation of a default constructor:

A(const A& a)=delete;//防拷贝

Two, lvalue and rvalue

1. Lvalue and lvalue reference

Variables and dereferenced variables are lvalues, we can get their addresses , lvalues ​​can appear on the left and right sides of assignment symbols, and rvalues ​​can only appear on the right side of assignment symbols.

int main()
{
    // 以下的p、b、c、*p都是左值
    int* p = new int(0);
    int b = 1;
    const int c = 2;
    // 以下几个是对上面左值的左值引用
    int*& rp = p;
    int& rb = b;
    const int& rc = c;
    int& pvalue = *p;
    return 0;
}

1. Lvalue references can only refer to lvalues, not rvalues.

2. But const lvalue references can refer to both lvalues ​​and rvalues ​​(permission translation)

int main()
{
    // 左值引用只能引用左值,不能引用右值。
    int a = 10;
    int& ra1 = a;   // ra为a的别名
    //int& ra2 = 10;   // 编译失败,因为10是右值
    // const左值引用既可引用左值,也可引用右值。
    const int& ra3 = 10;
    const int& ra4 = a;
    return 0;
}

2. Rvalues ​​and rvalue references

An rvalue is also an expression representing data, such as: literal constants, expression return values, function return values ​​(this cannot be an lvalue reference return), etc. Rvalues ​​can appear on the right side of an assignment symbol, but not in The left side of the assignment symbol, the rvalue cannot take the address . An rvalue reference is a reference to an rvalue, aliasing the rvalue. In C++11, rvalues ​​are divided into prvalues ​​(values ​​of built-in type expressions) and xvalues ​​(values ​​of expressions of custom types)

int main()
{
    double x = 1.1, y = 2.2;
    // 以下几个都是常见的右值
    10;
    x + y;
    fmin(x, y);
    // 以下几个都是对右值的右值引用
    int&& rr1 = 10;
    double&& rr2 = x + y;
    double&& rr3 = fmin(x, y);
    // 这里编译会报错:error C2106: “=”: 左操作数必须为左值
    10 = 1;
    x + y = 1;
    fmin(x, y) = 1;
    return 0;
}

1. Rvalue references can only refer to rvalues, not lvalues.

2. But rvalue references can refer to lvalues ​​after move.

int main()
{
     // 右值引用只能右值,不能引用左值。
     int&& r1 = 10;
     
     // error C2440: “初始化”: 无法从“int”转换为“int &&”
     // message : 无法将左值绑定到右值引用
     int a = 10;
     int&& r2 = a;
     // 右值引用可以引用move以后的左值
     int&& r3 = std::move(a);
     return 0;
}

2.1 The alias of rvalue is lvalue

The rvalue cannot take the address, but after giving the rvalue an alias, 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 value 10 cannot be taken, but after rr1 is referenced, You can take the address of rr1 or modify rr1, where rr1 is an lvalue . If you don't want rr1 to be modified, you can use const int&& rr1 to reference it. (This feature can also be reflected in move assignment. The move assignment parameter is an rvalue reference, and the purpose of assignment is completed by exchanging the object of this rvalue reference.)

int main()
{
     double x = 1.1, y = 2.2;
     int&& rr1 = 10;//rr1其实是一个左值
     const double&& rr2 = x + y;
     rr1 = 20;
     rr2 = 5.5;//报错  
     return 0;
}

Because the formal parameter of an rvalue reference is an lvalue, when passing layer by layer, this parameter needs to be moved to an rvalue:

void push_back(T&& x)//x为左值
{
	insert(end(),move(x));//需要用move转换为右值,不然会去调用左值版本的insert
}    
iterator insert(interator pos,T&& x)//x为左值
{
	node* newnode=new node(move(x));//需要用move转换为右值,不然会去调用左值版本的node构造函数
}
list_node(T&& x)//x是左值
	:_next(nullptr)
    ,_prev(nullptr)
    ,_data(move(x))//需要用move转换为右值,不然会去调用左值版本的T _data的构造函数
{}

However, if you write this way, you need to write one copy for the lvalue and one copy for the rvalue, and the code is repeated. The perfect forwarding method described below is more recommended.

2.2 Universal reference for templates

The && in the template does not represent an rvalue reference, but a universal reference, which can receive both lvalues ​​and rvalues. The universal reference of the template only provides the ability to receive lvalue references and rvalue references at the same time, but the only function of the reference type is to limit the type of reception, and it will degenerate into an lvalue in subsequent use. We hope to be able to pass In order to keep its lvalue or rvalue properties, you need to use perfect forwarding.

2.3 Perfect forwarding

std::forward perfect forwarding retains the original type properties of the object in the process of passing parameters. Of course, perfect forwarding also needs to be effective in the template environment. If it is not a template, T&& t will also be recognized as an rvalue reference.

Universal reference and perfect forwarding must ensure that the object is instantiated when passing parameters. If the template has been instantiated before passing parameters, it will not constitute universal reference and perfect forwarding.

Use perfect forwarding to modify the move writing in 2.1 of this section: Anyone who needs to pass parameters to the next layer and needs to keep rvalue attributes needs to use perfect forwarding.

template <class T>
void push_back(T&& x)//x可以接收任意类型
{
	insert(end(),std::forward<T>(x));
}    
iterator insert(interator pos,T&& x)///x可以接收任意类型
{
	node* newnode=new node(std::forward<T>(x));
}
list_node(T&& x)//x可以接收任意类型
	:_next(nullptr)
    ,_prev(nullptr)
    ,_data(std::forward<T>(x))
{}

3. The usage scenarios and meanings of lvalue references and rvalue references

3.1 Usage scenarios of lvalue references

Lvalue references can reduce copying when used in function passing parameters and function passing return values ​​(it must be ensured that the return value is still out of scope). If the return value of the function will be destroyed when it goes out of scope, you cannot use lvalue references to reduce copying (the object referenced after destruction is illegal), and you need to use rvalue references at this time. When there is no rvalue reference in C++, the method of output parameters can be used to solve the problem of returning multiple copies by value.

3.2 Usage scenarios of rvalue references

Scenario 1: The copy problem returned by passing value in a deep copy class

C++11 implements move construction and move assignment through rvalue references to solve the problem of returning multiple copies of values ​​and improve efficiency:

class string
{
public:
    //拷贝构造
    string(const string& s)//传入的s是左值,需要老老实实构造
    {
        string tmp(s.c_str());
        swap(tmp);
    }
    //移动构造
    string(string&& s)//传入的s是将亡值,可以换走s的成员
    {
        swap(s);//将s的成员直接换给*this,s消亡后自动调用析构函数
    }
	// 赋值重载
    string& operator=(const string& s)
    {
        string tmp(s);
        swap(tmp);
        return *this;
    }
	// 移动赋值
    string& operator=(string&& s)
    {
        swap(s);
        return *this;
    }
private:
    char* _str = nullptr;
    size_t _capacity = 0;
    size_t _size = 0;
};

For deep copy classes, C++11 uses rvalue references to implement move construction and move assignment . In scenarios where copying is required , resources that will be valued can be directly transferred. As shown in the figure below, although to_string is returned by value, but str is recognized by the compiler as a dying value, the compiler will call the move construction to construct ret1 in one step, and the cost is very low.

Scenario 2: Inserting rvalue data can also reduce copying

int main()
{
	list<string> it;
	string s1("1111");
	it.push_back(s1);//左值,深拷贝
	it.push_back(string("2222"));//右值,直接移动构造转移右值资源
	it.push_back("3333");//右值,直接移动构造转移右值资源
	return 0;
}

3. "Git from entry to proficiency" 

【brief introduction】 

        Git is a tool that feels easy to learn at first, but difficult to master. In addition to introducing the relevant knowledge of Git, this book also simulates various common situations to let readers know when to use which commands.
      "Git from Getting Started to Mastering" is divided into 11 chapters. Chapters 1~3 introduce the installation tools and environment. Readers who have already installed Git can start reading directly from Chapter 4. Chapter 5 introduces the basic usage of Git. Although it is not difficult, it is the basis of the entire Git system. Chapter 6 introduces the commonly used branch functions and usage scenarios in Git, and Chapters 7-9 introduce how to modify existing history records, use labels, and how to deal with other common situations.
        The previous content can be completed on your own computer, starting from Chapter 10 to introduce how to push a copy of the records in your computer to online (GitHub). *The last chapter (Chapter 11) introduces Git Flow, a development process that teams may use when developing.
        Most of the reference books or online tutorials on the market teach you how to learn Git through terminal commands, which discourages many novices who want to learn Git. In addition to teaching you how to input Git commands in the terminal window, this book is also equipped with a graphical interface tool, which eases the learning curve for readers and makes it easier for readers to get started.

Jingdong self-operated purchase link:

"Git from entry to proficiency" (Gao Jianlong) [Abstract Book Review Trial Reading]-Jingdong Books

 Book sending activity
This issue of the book is "Git from Beginner to Master" to send a copy 
of the lottery time: 2023-04-09-23:59
Participation method:
1. Like and collect the article
2. Leave a message in the comment area: Life is short, I Use Git (up to five messages)
3. The lottery method is a random lottery draw for comments in the comment area (random draw by the C language rand() function), and the winners will be announced in the comment area as scheduled, with free shipping.

おすすめ

転載: blog.csdn.net/gfdxx/article/details/130001994#comments_25958355