C++
-
左值和右值、
- 左值是能用在赋值语句等号左侧、代表一个地址、
- 为了对比左值所以出现了右值、与左值相反、
- 表达式先判断是否为左值、非左即右、没有其它选项、
- 左值可以当成右值使用、
- a=a+1——a是左值不是右值、a在右边是所以a有右值属性(非右值属性)、a左边代表地址、右边代表值、
- 一个左值可以同时具有右值属性和左值属性、变量是左值
- 可以将左值表达式理解为左值、而右值表达式便是右值、
- 赋值运算符、地址运算符、容器下标、迭代器递增递减、等均需要用到左值、只要运算符在字面值上能操作一般都需要左值、
- 左值表达式的求值结果是个对象、必须有地址、有地址不一定是左值、但是左值一定要有地址、地址是核心、
-
引用分类、
- 三种引用方式、
- 左值引用(绑定到左值)
- const引用(常量引用)是左值引用的一种、特点是、不能改变值的对象、
- 右值引用(绑定到右值)相当于为左值引用而生、其主要作用是临时的引用、
- 右值引用使用 &&a=1 1便是临时的值、临时保存、
- 三种引用方式、
-
左值引用、
-
将变量值绑定到左值上便是左值引用、大部分都是左值引用、
-
引用一定要绑定一个数值、不像指针有空指针、引用没有空引用、初始化绑定、引用必须初始化、
-
左值引用必须绑定到左值不能绑定给到右值
-
int a=3//左值因为变脸便是左值、 int &c=a//绑定左值、 int &a1=++b//左值
-
任何函数里面的形参都是做左值、
-
-
右值引用、
-
右值引用的引用目的、
- 绑定一些即将销毁的或者临时的对象上、
- 右值引用 && 代表新的数据类型、
- 目的是通过把拷贝对象变成移动对象来提高运行效率、
- 移动对象是替代拷贝对象而出现的、将a移动到b、方式是a自己开辟了内存、b也需开辟内存存储数据、移动对象就是b不再开辟内容而直接将a的内存给b、将a的内存直接移交给b、或者b偷a的所有内存、
- 移动对象后a便不能再使用、
- 右值引用是为了应付移动构造函数和移动赋值运算符而用的、
-
必须是绑定到右值的引用、
-
右值引用也是引用 即对象的名字、
-
右值引用也是有地址的、
-
左值不能绑定到临时变量、临时变量有地址但是系统将其当成右值、
-
要想将临时变量绑到左值可以使用const引用、const引用不仅可以绑定还可以执行隐式转换并将值放到临时变量中、
-
int e; int a = e; int e = 10; int& c = a; int&& d = 100;//右值
-
-
std::move函数、
-
将左值强制转换成右值、唯一的作用、
-
没有移动的功能、
-
int a = 29; int&& b = std::move(a);//强行绑定、也是move的唯一作用、
-
将b和a绑定在一起、改变b、a也会改变、改变a、b也会改变、
-
int a = 29; int&& b = std::move(a);//强行绑定、也是move的唯一作用、 string c = "这是字符串";//运行后c的内容为空、 const char* f = c.c_str(); string e = std::move(c);//其实是、std::move触发了string里面的函数、将c里面的内容清空啦、 string是移动构造函数、将c的值移动到e里面、 const char* s = e.c_str(); cout << c << endl; cout << e << endl; cout << b << endl;
-
转移并非是move做的、e是重新开辟的内存存储c的内容、
-
c和e均各有自己的内存、
-
string &&e = std::move(c) 这样就不会触发string的内部函数、而是右值引用、
-
-
总结、
-
左值绑定左值、右值绑定右值、const则可以绑定右值或左值、
-
a– –(后置递增或递减运算符)返回右值、— —a (前置递增或递减运算符)返回的是左值、
-
int a = 1; int&& b = a++;//右值、b和a没有任何关系 int& c = ++a;//左值、
-
系统不建议执行move后继续使用移动的值、也就是 c 但是、后续仍然可以使用、
-
int a = 29; int&& b = std::move(a);//强行绑定、也是move的唯一作用、 string c = "这是字符串";//运行后c的内容为空、 const char* f = c.c_str(); string &&e = std::move(c);//系统不让使用在以后的代码中出现c const char* s = e.c_str(); c = "abc";//后续仍然可以使用、 //e = "aaa"; cout << c << endl; cout << e << endl; cout << b << endl;
-