当前位置: 首页 > news >正文

网站对于一个企业的优势聊城做网站的公司效果

网站对于一个企业的优势,聊城做网站的公司效果,网站后台百度商桥代码哪里安装,wordpress占内存#x1fae7; 励志不掉头发的内向程序员#xff1a;个人主页✨️ 个人专栏: 《C语言》《Linux学习》#x1f305;偶尔悲伤#xff0c;偶尔被幸福所完善 #x1f453;️博主简介: 文章目录前言一、左值和右值二、左值引用和右值引用三、引用延长生命周期四、左值和右值的参… 励志不掉头发的内向程序员个人主页✨️ 个人专栏: 《C语言》《Linux学习》偶尔悲伤偶尔被幸福所完善 ️博主简介: 文章目录前言一、左值和右值二、左值引用和右值引用三、引用延长生命周期四、左值和右值的参数匹配五、右值引用和移动语义的使用场景5.1、左值引用主要使用场景回顾5.2、移动构造和移动赋值5.3、右值引用和移动语义解决传值返回问题1右值对象构造只有拷贝构造没有移动构造的场景2右值对象构造有拷贝构造也有移动构造的场景3右值对象赋值只有拷贝构造和拷贝赋值没有移动构造和移动赋值的场景4右值对象赋值既有拷贝构造和拷贝赋值也有移动构造和移动赋值的场景5.4、右值引用和移动语义在传参中的提效六、类型分类七、引用折叠八、完美转发总结前言 C98 的 C 语法中就已经有引用的语法了而 C11 中新增了的右值引用的语法特性C11 之后我们之前学习的引用就叫做左值引用。无论左值引用还是右值引用都是给对象取别名。我们本章节就来了解了解它们的区别以及作用吧。 一、左值和右值 左值引用从我们了解 C 的第一课就已经是开始学习了但是右值引用是什么呢它的出现到底有什么意义的我们来看看吧。 左值是⼀个表示数据的表达式如变量名或解引用的指针一般是有持久状态存储在内存中我们可以获取它的地址左值可以出现在赋值符号的左边也可以出现在赋值符号的右边。定义时 const 修饰符后的左值不能给他赋值但是可以取它的地址 // 左值可以取地址 // Type x// 以下的p、b、c、*p、s、s[0]就是常⻅的左值 int* p new int(0); int b 1; const int c b; *p 10; string s(111111); s[0] x;cout c endl; cout (void*)s[0] endl;右值也是一个表示数据的表达式要么是字面值常量、要么是表达式求值过程中创建的临时对象等右值可以出现在赋值符号的右边但是不能出现出现在赋值符号的左边右值不能取地址 // 右值不能取地址 // Type ydouble x 1.1, y 2.2;// 以下⼏个10、x y、fmin(x, y)、string(11111)都是常⻅的右值 10; x y; fmin(x, y); string(11111); cout 10 endl; cout (xy) endl; cout (fmin(x, y)) endl; cout string(11111) endl;值得一提的是左值的英文简写为 lvalue右值的英文简写为 rvalue。传统认为它们分别是 left value、right value 的缩写。现代 C 中lvalue 被解释为 loactor value 的缩写可意为存储在内存中、有明确存储地址可以取地址的对象而 rvalue 被解释为 read value指的是那些可以提供数据值但是不可以寻址例如临时变量字面值常量存储于寄存器中的变量等也就是说左值和右值的核心区别就是能否取地址 二、左值引用和右值引用 Type r1 x; Type rr1 y; 第一个语句就是左值引用左值引用就是给左值取别名第二个就是右值引用同样的道理右值引用就是给右值取别名 // 左值可以取地址 // 以下的p、b、c、*p、s、s[0]就是常⻅的左值 int* p new int(0); int b 1; const int c b; *p 10; string s(111111); s[0] x; double x 1.1, y 2.2;// 左值引⽤给左值取别名 int r1 b; int* r2 p; int r3 *p; string r4 s; char r5 s[0];// 右值引⽤给右值取别名 int rr1 10; double rr2 x y; double rr3 fmin(x, y); string rr4 string(11111);左值引用不能直接引用右值但是 const 左值引用可以引用右值右值引用不能直接引用左值但是右值引用可以引用 move左值 // 左值引⽤不能直接引⽤右值但是const左值引⽤可以引⽤右值 const int rx1 10; const double rx2 x y; const double rx3 fmin(x, y); const string rx4 string(11111);// 右值引⽤不能直接引⽤左值但是右值引⽤可以引⽤move(左值) int rrx1 move(b); int* rrx2 move(p); int rrx3 move(*p); string rrx4 move(s); string rrx5 (string)s;由于我们一般右值都是一些临时变量字面值常量等具有常性的变量如果我们左值直接去引用就相当于权限扩大了所以我们必须 const 引用才行。 同时我们需要主要我们不管去用左值引用右值还是用右值去引用左值我们变量本身的性质是不会改变的因为引用本身只是去去个别名不会因为你左值引用/右值引用去引用右值/左值了右值/左值就会变成左值/右值。 move是库里面的一个函数模板本质内部是进行强制类型转换当然他还涉及一些引用折叠的知识这个我们后面会细讲 需要注意的是变量表达式都是左值属性也就意味着一个右值被右值引用绑定后右值引用变量表达式的属性是左值 // 这⾥要注意的是rr1的属性是左值所以不能再被右值引⽤绑定除⾮move⼀下 int rr1 10; int r6 rr1;如果上图还是不好理解的话我们可以简略的这样理解。 就和我们创建一个内存空间时用一个指针来接收是同一个原理我们空间是在堆上的但是指针是在栈上的只不过通过指针就能找到我们创建的空间而已这里也是一样的。我们设计者这么设计其实是有原因的我们后面在细细说来。 语法层面看左值引用和右值引用都是取别名不开空间。从汇编底层的⻆度看代码中 r1 和 rr1 汇编层实现底层其实都是用指针实现的没什么区别。底层汇编等实现和上层语法表达的意义有时是背离的所以不要揉到一起去理解互相佐证这样反而容易陷入迷途 三、引用延长生命周期 右值引用可用于为临时对象延长生命周期const 的左值引用也能延长临时对象生存期但这些对象无法被修改。 std::string s1 Test; // std::string r1 s1; // 错误不能绑定到左值 const std::string r2 s1 s1; // OK到 const 的左值引用延长生存期// r2 Test; // 错误不能通过到 const 的引用修改 std::string r3 s1 s1; // OK右值引用延长生存期 r3 Test; // OK能通过到非 const 的引用修改std::cout r3 \n;四、左值和右值的参数匹配 C98 中我们实现一个 const 左值引用作为参数的函数那么实参传递左值和右值都可以匹配C11 以后分别重载左值引用、const 左值引用、右值引用作为形参的 f 函数那么实参是左值会匹配 f左值引用实参是 const 左值会匹配 fconst 左值引用实参是右值会匹配 f右值引用右值引用变量在用于表达式时属性是左值这个设计这里会感觉很怪下一小节我们讲右值引用的使用场景时就能体会这样设计的价值了 void f(int x) {std::cout 左值引⽤重载 f( x )\n; } void f(const int x) {std::cout 到 const 的左值引⽤重载 f( x )\n; } void f(int x) {std::cout 右值引⽤重载 f( x )\n; } int main() {int i 1;const int ci 2;f(i); // 调⽤ f(int)f(ci); // 调⽤ f(const int)f(3); // 调⽤ f(int)如果没有 f(int) 重载则会调⽤ f(const int)f(std::move(i)); // 调⽤ f(int)// 右值引⽤变量在⽤于表达式时是左值int x 1;f(x); // 调⽤ f(int x)f(std::move(x)); // 调⽤ f(int x)return 0; }五、右值引用和移动语义的使用场景 5.1、左值引用主要使用场景回顾 左值引用主要使用场景是在函数中左值引用传参和左值引用传返回值时减少拷贝同时还可以修改实参和修改返回对象的价值。左值引用已经解决大多数场景的拷贝效率问题但是有些场景不能使用传左值引用返回如 addStrings 和 generate 函数C98 中的解决方案只能是被迫使用输出型参数解决。那么 C11 以后可以使用右值引用做返回值解决吗显然是不可能的因为这里的本质是返回对象是一个局部对象函数结束这个对象就析构销毁了右值引用返回也无法改变对象已经析构销毁的事实。 class Solution { public:// 传值返回需要拷贝string addStrings(string num1, string num2) {string str;int end1 num1.size() - 1, end2 num2.size() - 1;// 进位int next 0;while (end1 0 || end2 0){int val1 end1 0 ? num1[end1--] - 0 : 0;int val2 end2 0 ? num2[end2--] - 0 : 0;int ret val1 val2 next;next ret / 10;ret ret % 10;str (0 ret);}if (next 1)str 1;reverse(str.begin(), str.end());return str;} };class Solution { public:// 这里的传值返回拷贝代价就太大了vectorvectorint generate(int numRows) {vectorvectorint vv(numRows);for (int i 0; i numRows; i){vv[i].resize(i 1, 1);}for (int i 2; i numRows; i){for (int j 1; j i; j){vv[i][j] vv[i - 1][j] vv[i - 1][j - 1];}}return vv;} };这两个函数的返回值是在函数中创建的局部对象此时如果返回后我们的函数销毁我们的局部对象也就销毁了如果我们用一个指针指向它们就相当于一个野引用所以我们不能这样做。 5.2、移动构造和移动赋值 移动构造函数是一种构造函数类似拷贝构造函数移动构造函数要求第一个参数是该类类型的引用但是不同的是要求这个参数是右值引用如果还有其他参数额外的参数必须有缺省值移动赋值是⼀个赋值运算符的重载他跟拷贝赋值构成函数重载类似拷贝赋值函数移动赋值函数要求第一个参数是该类类型的引用但是不同的是要求这个参数是右值引用对于像 string/vector 这样的深拷贝的类或者包含深拷贝的成员变量的类移动构造和移动赋值才有意义因为移动构造和移动赋值的第一个参数都是右值引用的类型他的本质是要 “窃取” 引用的右值对象的资源而不是像拷贝构造和拷贝赋值那样去拷贝资源从提高效率。下面的 zxl::string 样例实现了移动构造和移动赋值我们需要结合场景理解 namespace zxl {class string{public:typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}iterator end(){return _str _size;}const_iterator begin() const{return _str;}const_iterator end() const{return _str _size;}string(const char* str ):_size(strlen(str)), _capacity(_size){cout string(char* str)-构造 endl;_str new char[_capacity 1];strcpy(_str, str);}void swap(string s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}string(const string s):_str(nullptr){cout string(const string s) -- 拷⻉构造 endl;reserve(s._capacity);for (auto ch : s){push_back(ch);}}// 移动构造string(string s){cout string(string s) -- 移动构造 endl;swap(s);}string operator(const string s){cout string operator(const string s) -- 拷⻉赋值 endl;if (this ! s){_str[0] \0;_size 0;reserve(s._capacity);for (auto ch : s){push_back(ch);}}return *this;}// 移动赋值string operator(string s){cout string operator(string s) -- 移动赋值 endl;swap(s);return *this;}~string(){cout ~string() -- 析构 endl;delete[] _str;_str nullptr;}char operator[](size_t pos){assert(pos _size);return _str[pos];}void reserve(size_t n){if (n _capacity){char* tmp new char[n 1];if (_str){strcpy(tmp, _str);delete[] _str;}_str tmp;_capacity n;}}void push_back(char ch){if (_size _capacity){size_t newcapacity _capacity 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] ch;_size;_str[_size] \0;}string operator(char ch){push_back(ch);return *this;}const char* c_str() const{return _str;}size_t size() const{return _size;}private:char* _str nullptr;size_t _size 0;size_t _capacity 0;}; }此时就能够看出为什么我们设计者要把右值引用的属性设置为左值了因为我们移动构造和移动赋值要去掠夺我们右值引用的资源如果是右值就不能够掠夺了所以为此我们把它设计成左值从而实现掠夺效果。 5.3、右值引用和移动语义解决传值返回问题 1右值对象构造只有拷贝构造没有移动构造的场景 namespace zxl {string addStrings(string num1, string num2){string str;int end1 num1.size() - 1, end2 num2.size() - 1;int next 0;while (end1 0 || end2 0){int val1 end1 0 ? num1[end1--] - 0 : 0;int val2 end2 0 ? num2[end2--] - 0 : 0;int ret val1 val2 next;next ret / 10;ret ret % 10;str (0 ret);}if (next 1)str 1;reverse(str.begin(), str.end());cout ****************************** endl;return str;} }int main() {zxl::string ret zxl::addStrings(11111, 2222);cout ret.c_str() endl;return 0; }下图展示了 vs2019 debug 环境下编译器对拷贝的优化左边为不优化的情况下两次拷贝构造右边为编译器优化的场景下连续步骤中的拷贝合二为一变为一次拷贝构造 正常来说当我们使用我们的匿名对象去传参时我们编译器都会先调用构造函数先给匿名对象构造一个临时变量然后我们的临时变量此时就会去拷贝构造传给我们的形参。但是这样太过于浪费效率了所以我们 C 为了避免就优化了这两个步骤使其合二为一。 需要注意的是在 vs2019 的 release 和 vs2022 的 debug 和 release下面代码优化为非常恐怖会直接将 str 对象的构造str 拷贝构造临时对象临时对象拷贝构造 ret 对象合三为一变为直接构造。要理解这个优化要结合局部对象生命周期和栈帧的角度理解 我们第三种优化不单单没有产生临时变量甚至连 str 都没有产生而是产生了一个临时变量的引用也就是我们 str 变成了 ret 的引用我们可以打印地址来看看它们的地址是否相同。 namespace zxl {string addStrings(string num1, string num2){string str;int end1 num1.size() - 1, end2 num2.size() - 1;int next 0;while (end1 0 || end2 0){int val1 end1 0 ? num1[end1--] - 0 : 0;int val2 end2 0 ? num2[end2--] - 0 : 0;int ret val1 val2 next;next ret / 10;ret ret % 10;str (0 ret);}if (next 1)str 1;reverse(str.begin(), str.end());cout ****************************** endl;cout str endl; // 取 str 地址看看是不是 ret 的别名return str;} }int main() {zxl::string ret zxl::addStrings(11111, 2222);cout ret.c_str() endl;cout ret endl;return 0; }2右值对象构造有拷贝构造也有移动构造的场景 上面是不包含我们的移动构造的场景此时我们来看看包含了移动构造的场景是怎么样的。 下图展示了 vs2019 debug 环境下编译器对拷贝的优化左边为不优化的情况下两次移动构造右边为编译器优化的场景下连续步骤中的拷贝合二为一变为一次移动构造。 此时我们和之前一样只不过由于我们函数传过去的是右值之前没有移动构造就会匹配普通的构造现在有了就会匹配我们的移动构造。由于移动构造是对我们的资源进行掠夺所以对资源的消耗和普通构造相比是极低的相当于没有所以此时我们的函数优化前和优化后其实效率的区别已经不是特别大了。 需要注意的是在 vs2019 的 release 和 vs2022 的 debug 和 release下面代码优化为非常恐怖会直接将 str 对象的构造str 拷贝构造临时对象临时对象拷贝构造 ret 对象合三为一变为直接构造。要理解这个优化要结合局部对象生命周期和栈帧的角度理解 3右值对象赋值只有拷贝构造和拷贝赋值没有移动构造和移动赋值的场景 下图左边展示了 vs2019 debug 和 g test.cpp -fno-elide-constructors 关闭优化环境下编译器的处理⼀次拷贝构造⼀次拷贝赋值 上面的图已经解释清楚了此处就不过多赘述。 需要注意的是在 vs2019 的 release 和 vs2022 的 debug 和 release下面代码会进一步优化直接构造要返回的临时对象str 本质是临时对象的引用底层⻆度用指针实现。运行结果的角度我们可以看到 str 的析构是在赋值以后说明 str 就是临时对象的别名 4右值对象赋值既有拷贝构造和拷贝赋值也有移动构造和移动赋值的场景 下图左边展示了 vs2019 debug 和 g test.cpp -fno-elide-constructors 关闭优化环境下编译器的处理⼀次移动构造⼀次移动赋值 需要注意的是在 vs2019 的 release 和 vs2022 的 debug 和 release下面代码会进一步优化直接构造要返回的临时对象str 本质是临时对象的引用底层⻆度用指针实现。运行结果的⻆度我们可以看到 str 的析构是在赋值以后说明 str 就是临时对象的别名 我们的移动语义出现后我们对 C 的优化存在与否就已经不重要了因为我们不管优化还是不优化效率有了移动语义效率都是非常低的。而且我们的优化只是编译器的个人行为而非统一行为所以我们可能换个编译器优化就没了非常不靠谱但是我们移动语义是 C 就包含的特性。当然这些各种各样的优化的出现其实也是因为 C11 里 C98 相差 13 年没更新程序猿的无奈之举罢了不然就不会有这些优化了所以说托更害人啊。 5.4、右值引用和移动语义在传参中的提效 查看 STL 文档我们发现 C11 以后容器的 push 和 insert 系列的接口增加的右值引用版本当实参是一个左值时容器内部继续调用拷贝构造进行拷贝将对象拷贝到容器空间中的对象当实参是一个右值容器内部则调用移动构造右值对象的资源到容器空间的对象上其实这里还有一个 emplace 系列的接口但是这个涉及可变参数模板我们需要把可变参数模板讲解以后再讲解 emplace 系列的接口 六、类型分类 C11 以后进一步对类型进行了划分右值被划分纯右值pure value简称prvalue和将亡值expiring value简称xvalue纯右值是指那些字面值常量或求值结果相当于字面值或是一个不具名的临时对象。如42、true、nullptr 或者类似 str.substr(1, 2)、str1 str2 传值返回函数调⽤或者整形 a、b、a、ab 等。纯右值和将亡值 C11 中提出的C11 中的纯右值概念划分等价于 C98 中的右值将亡值是指返回右值引用的函数的调用表达式和转换为右值引用的转换函数的调⽤表达如 move(x)、static_castX(x)泛左值generalized value简称glvalue泛左值包含将亡值和左值 这个语法只是对类型进行划分其实不是特别的重要了解一下即可。 七、引用折叠 C 中不能直接定义引用的引用如 int r i; 这样写会直接报错通过模板或 typedef 中的类型操作可以构成引用的引用通过模板或 typedef 中的类型操作可以构成引用的引用时这时 C11 给出了一个引用折叠的规则右值引用的右值引用折叠成右值引用所有其他组合均折叠成左值引用下面的程序中很好的展示了模板和 typedef 时构成引用的引用时的引用折叠规则大家需要一个一个仔细理解一下 bash typedef int lref; typedef int rref;int n 0;lref r1 n; // r1 的类型是 int lref r2 n; // r2 的类型是 int rref r3 n; // r3 的类型是 int rref r4 1; // r4 的类型是 int我们可以看到我们前 3 个引用就被折叠了。只有两个都是右值引用时才会折叠成右值引用否则就都是左值引用。 像 f2 这样的函数模板中T x参数看起来是右值引用参数但是由于引用折叠的规则他传递左值时就是左值引用传递右值时就是右值引用有些地方也把这种函数模板的参数叫做万能引用Function(T t) 函数模板程序中假设实参是 int 右值模板参数 T 的推导 int实参是 int 左值模板参数 T 的推导 int再结合引用折叠规则就实现了实参是左值实例化出左值引用版本形参的 Function实参是右值实例化出右值引用版本形参的 Function 我们在现实中一般都是这样使用引用折叠的。 // 由于引⽤折叠限定f1实例化以后总是⼀个左值引⽤ templateclass T void f1(T x) {}我们写了一个左值引用的函数模板此时我们去传参。 // 没有折叠-实例化为void f1(int x) f1int(n); f1int(0); // 报错我们会发现当我们传递右值时无法传过去此时并没有发生引用折叠。 // 折叠-实例化为void f1(int x) f1int(n); f1int(0); // 报错此时我们这里发生了引用折叠此时按道理我们的 f1 的参数 T x应该实例化成 int x但是由于引用折叠实际上是实例化成 int x。 // 折叠-实例化为void f1(int x) f1int(n); f1int(0); // 报错虽然这里传了右值引用给模板但是由于引用折叠所以实例化出来的依旧是左值引用所以依旧报错。 // 折叠-实例化为void f1(const int x) f1const int(n); f1const int(0);// 折叠-实例化为void f1(const int x) f1const int(n); f1const int(0);这两个实例化出来的经过折叠依然是左值引用但是由于是 const 支持引用右值而不是说是实例化为右值。 由于引用折叠的限制我们的 f1 无论如何都是一个左值引用。 // 由于引⽤折叠限定f2实例化后可以是左值引⽤也可以是右值引⽤ templateclass T void f2(T x) {}如果我们的模板是一个右值此时我们就能达到一个传左值就是左值传右值就是右值的效果啦。 // 没有折叠-实例化为void f2(int x) f2int(n); // 报错 f2int(0);// 折叠-实例化为void f2(int x) f2int(n); f2int(0); // 报错// 折叠-实例化为void f2(int x) f2int(n); // 报错 f2int(0);向上面的这种模板我们有的地方也称之为万能引用。 当然如果我们传参传的是 int 型那我们的形参也是右值引用但是我们 T 是 int。 templateclass T void f2(T x) {int a 1;T b a;cout a endl;cout b endl; }int main() {f2(1);return 0; }此时我们可以看到我们的地址不相同所以 T 被推导成了 int。 但是如果我们此时传一个左值给 f2那我们的 T 是否还会推导成 T 呢 int main() {int a 0;f2(a);return 0; }此时我们发现我们的 b 的地址和 a 的地址是一样的也就是说我们的 T 被推导成 int 了。 如果传过去的是 const int我们 T 推导的就是 const int。 templateclass T void f2(T x) {int a 1;T b a;b;cout a endl;cout b endl;}int main() {const int a 0;f2(a);return 0; }如果我们使用 move(b) 右值那推导出来的 T 就会变成 const int。 int main() {// std::move(b)右值推导出T为const int模板实例化为void f2(const int t)// 所以f2内部会编译报错b不能const int b 8;f2(std::move(b)); // const 右值return 0; }八、完美转发 Function(T t) 函数模板程序中传左值实例化以后是左值引用的 Function 函数传右值实例化以后是右值引用的 Function 函数 但是结合我们上面的讲解变量表达式都是左值属性也就意味着一个右值被右值引用绑定后右值引用变量表达式的属性是左值也就是说 Function 函数中 t 的属性是左值那么我们把 t 传递给下一层函数 Fun那么匹配的都是左值引用版本的 Fun 函数。这⾥我们想要保持 t 对象的属性就需要使用完美转发实现 template T forward (typename remove_reference::type arg); template T forward (typename remove_reference::type arg) 完美转发 forward 本质是一个函数模板他主要还是通过引用折叠的方式实现下面示例中传递给 Function 的实参是右值T 被推导为 int没有折叠forward 内部 t 被强转为右值引用返回传递给 Function 的实参是左值T 被推导为 int引用折叠为左值引用forward 内部 t 被强转为左值引用返回 我们的程序有的时候会出现一些退化的问题此时我们就要用到完美转发啦。 造成退化的问题主要是我们的右值引用属性是左值导致的此时我们把含有左值属性的变量传递下去那就变成了左值了。但是我们不想这样做。 void Fun(int x) { cout 左值引用 endl; } void Fun(const int x) { cout const 左值引用 endl; } void Fun(int x) { cout 右值引用 endl; } void Fun(const int x) { cout const 右值引用 endl; } templateclass T void Function(T t) {Fun(t); }int main() {// 10是右值推导出T为int模板实例化为void Function(int t)Function(10); // 右值int a;// a是左值推导出T为int引⽤折叠模板实例化为void Function(int t)Function(a); // 左值// std::move(a)是右值推导出T为int模板实例化为void Function(int t)Function(std::move(a)); // 右值const int b 8;// a是左值推导出T为const int引⽤折叠模板实例化为void Function(const int t)Function(b); // const 左值// std::move(b)右值推导出T为const int模板实例化为void Function(const int t)Function(std::move(b)); // const 右值return 0; }我们看上面的这一串代码我们这些代码有的是传左值有的是传右值实例化出来的也应该有的是左值有的是右值但是为什么当我们去调用 Fun 函数时都变成了左值 原因就是我们上面所说的我们右值引用属性是左值那调用 Fun 是不就变成了左值啦。所以 C11 中为了避免发生这样的事情就发明了一个叫做完美转发的操作。 这是一个函数模板它的使用方法也非常简单。 void Function(T t) {Fun(forwardT(t)); }只要给会退化的地方套用这个函数模板就可以解决退化问题了。 完美转发的作用就是保持属性向下传递不会改变。它相当于是推导 T 如果是 int 等就相当于是右值然后把我们的参数强转一下传递下去如果是 int那就是左值就直接传递。 总结 这就是我们的右值引用和移动语义的用法啦还是比较复杂的大家好好理解它的存在其实是非常重要的现在的各种编译器的优化之所以存在就是因为它出现的太晚了我们大家得好好掌握。 坚持到这里已经很厉害啦辛苦啦 ʕ • ᴥ • ʔ づ♡ど
http://www.pierceye.com/news/916291/

相关文章:

  • 直播网站开发秀色上海综合新闻
  • 电子商务网站建设与管理课后题答案企业网站推广哪家好
  • 网站被挂黑链怎么删除石家庄企业网站建设
  • 网站模板怎么连接域名可视化网页设计在线
  • 美术馆网站建设要求开发软件多少钱一个月
  • 直播网站开发核心技术wordpress访问次数插件
  • wap网站 劣势微信小程序怎么写
  • 商业网站开发与设计网站seo是什么意思
  • 内蒙古住房和城乡建设网站做网站的人怎么上传内容的
  • 视频网站视频预览怎么做的美丽说网站案例分析
  • 宝安多屏网站建设公司好吗网站启用cdn加速
  • 上海网站制作方法网站页面设计报价
  • 介绍自己做的网站的论文网站模块建设中
  • 诸城手机网站建设微官网怎么制作
  • 做网站界面的软件网站开发售后服务
  • 织梦可以做英文网站吗成交型网站建设公司
  • 长沙招聘网站制作广告设计公司需要用专线网吗
  • 一级做爰A视频免费网站国内疫苗接种率
  • 绍兴网站公司网站制作163邮箱登录页面
  • 阐述电子商务网站的建设要求网站开发总结性报告
  • html与wordpressaso优化方法
  • 众v创业营网站开发营销活动方案策划
  • 什么网站免费做推广抚州北京网站建设
  • 响应式网站 软件做网站下载那个数据库好
  • 网站loading动画效果微信开放平台介绍
  • 山东网站建设报价网页制作与网站建设答案
  • 佛山网站搭建费用淄博刚刚发布紧急通知
  • 建站教程视频下载视频直播软件开发
  • 后缀cc的网站php网站开发实例教程代码百度云
  • 注册好域名之后怎么做个人网站如何用服务器代替空间做网站