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

网站建设 源代码归属免费注册qq号

网站建设 源代码归属,免费注册qq号,哪些网站可以找到做海报的素材,江苏省住房和城乡建设部网站文章目录一、左值引用、 右值引用1.1 左值与右值1.2 左值引用1.3 右值引用二、右值引用的意义三、移动语句3.1 移动构造3.2 移动赋值3.3 总结四、move问题五、完美转发5.1 万能引用与折叠5.2 完美转发std::forward一、左值引用、 右值引用 1.1 左值与右值 我们经常能听到左值… 文章目录一、左值引用、 右值引用1.1 左值与右值1.2 左值引用1.3 右值引用二、右值引用的意义三、移动语句3.1 移动构造3.2 移动赋值3.3 总结四、move问题五、完美转发5.1 万能引用与折叠5.2 完美转发std::forward一、左值引用、 右值引用 1.1 左值与右值 我们经常能听到左值和右值那么我们怎么判断左值和右值呢 C中还有一个被广泛认同的说法 那就是可以取地址的、 有名字的就是左值 反之不能取地址的、 没有名字的就是右值。 左值可以出现在左边和右边而右值不能出现在左边。 举个例子 a是个左值ab就是个右值 因为可以对a取地址a 但是不能对a b取地址(a b) 左值和右值不是个变量而是个数据表达式。 左值一般有变量名或解引用的指针 右值一般有字面常量、表达式返回值函数返回值 1.2 左值引用 左值引用就是给左值起别名。 int main() {// 左值int a 0;int* b nullptr;const int c 1;const int* d nullptr;// 左值引用int ra a;int* rb b;const int rc c;const int* rd d;// 左值引用不能引用右值但const左值引用可以//int e 10;//int f (a c);const int e 10;const int f (a c);return 0; }1.3 右值引用 右值引用只能引用右值不能引用左值。 但是右值引用可以move以后的左值move可以把ret变成一个将亡值(右值)。 int main() {// 只能引用右值int a 10;a;// 右值引用后变左值int ret 0;//int b ret;// 不能引用左值// 可以引用move后的左值int b std::move(ret);return 0; }const引用既可以引用左值也可以引用右值。 二、右值引用的意义 我们以前使用的引用基本上都是左值引用函数传参函数传返回值左值引用的作用主要用来减少拷贝。 但是左值引用并没有彻底的解决传返回值的时候如果是一个局部变量我们就无法引用返回了。 template class T T fun() {T a;return a; }这里出了作用域后对象自动销毁所以不能传递回去造成越界访问。 为了解决这种情况我们就需要右值引用接下来用我们之前写过的string类举例子方便观察。 namespace yyh {class string{public:typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str _size;}string(const char* str ):_size(strlen(str)), _capacity(_size){_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){cout string(const string s) -- 深拷贝 endl;string tmp(s._str);swap(tmp);}// 赋值重载string operator(const string s){cout string operator(string s) -- 深拷贝 endl;string tmp(s);swap(tmp);return *this;}~string(){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];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;}private:char* _str nullptr;size_t _size 0;size_t _capacity 0;};string Get(){string s 123456;return s;} }int main() {yyh::string ret yyh::Get();return 0; }这里本来应该是Get返回的时候先拷贝一个临时对象再用这个临时对象拷贝给ret但是编译器经过优化可以直接拷贝给ret只调用一次拷贝构造。 不经过优化 如果对象较小就放到寄存器如果较大就在两个栈帧之间创建一个栈帧压返回值。 但是就算经过了优化也还是要拷贝如果要返回的对象非常大就会有大消耗。 三、移动语句 3.1 移动构造 右值又分为纯右值和将亡值 纯右值内置类型的表达式的值。 将亡值自定义类型表达式的值。 对于一个将亡值与其让它消失还不如直接把它的值交换走换给有需要的对象。 所以我们可以写一个拷贝构造的重载。 // 拷贝构造 string(const string s) {cout string(const string s) -- 深拷贝 endl;string tmp(s._str);swap(tmp); }// 移动构造 string(string s) {cout string(string s) -- 移动拷贝 endl;swap(s); }这里如果是左值就会匹配拷贝构造如果是右值就会匹配移动构造。 结果 3.2 移动赋值 上边解决了拷贝的问题接下来解决赋值问题。 这里会调用string(const string s)是因为operator使用的是现代写法。 // 赋值重载 string operator(const string s) {cout string operator(string s) -- 深拷贝 endl;string tmp(s);swap(tmp);return *this; }// 移动赋值 string operator(string s) {cout string operator(string s) -- 移动赋值 endl;swap(s);return *this; }3.3 总结 左值引用和右值引用减少拷贝的方式不太一样。 左值引用是直接取别名。 右值引用是使用移动构造和移动拷贝间接实现可以把要返回的临时对象看作将亡值进行资源转移。 右值引用主要解决的是对象传值返回拷贝问题。也可以解决容器插入数据的拷贝问题如果插入的是右值就不需要深拷贝。 四、move问题 我们知道move可以把一个左值变成右值但是有可能会出现问题 int main() {yyh::string s1(aaaaa);yyh::string s2(std::move(s1));return 0; }移动构造把资源转移后原来的对象的资源就消失了。 void fun2(int i) {cout fun2(int i) endl; }void fun2(int i) {cout fun2(int i) endl; }void fun1(int i) {cout fun1(int i) endl;fun2(i); }int main() {fun1(1);return 0; }这里为什么在fun1函数中没有调用void fun2(int i)呢 因为右值引用后就会变成左值而左值就会对应调用void fun2(int i)。 如果我们想让fun1调用void fun2(int i) void fun1(int i) {cout fun1(int i) endl;fun2(std::move(i)); }但是如果有多层嵌套函数就会频繁使用move所以C11引入新语法完美转发std::forward 五、完美转发 5.1 万能引用与折叠 上面我们区分左值和右值是通过两个函数的参数来区分。 在普通函数里右值不能引用左值 void fun1(int i) {cout fun1(int i) endl; }int main() {int a 1;//fun1(a);// 右值不能引用左值return 0; }所以C11提供了万能引用 // 万能引用 template class T void fun(T i) {cout fun(int i) endl; }int main() {int a 1;fun(a);// 左值fun(std::move(a));// 右值const int b 1;fun(b);// const左值fun(std::move(b));// const右值return 0; }这样就可以既引用左值/const左值 也可以引用右值/const右值。 完美转发是指在函数模板中完全依照模板的参数的类型将参数传递给函数模板中调用的另外一个函数。 实例化出以下类型的不同函数 5.2 完美转发std::forward 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; }// 万能引用 template class T void fun(T i) {Fun(i); }int main() {int a 1;fun(a);// 左值fun(std::move(a));// 右值const int b 1;fun(b);// const左值fun(std::move(b));// const右值return 0; }我们可以看出这个fun函数把所有的全部转化为左值不是我们想要的。 所以就有了完美转发std::forward 完美转发适用于这样的场景 需要将一组参数原封不动的传递给另一个函数。 而且原封不动传递的不仅仅是参数的数值还包括左值/右值const/非const这些性质。 // 万能引用 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; }// 万能引用 template class T void fun(T i) {// 完美转发保持原本属性Fun(std::forwardT(i)); }int main() {int a 1;fun(a);// 左值fun(std::move(a));// 右值const int b 1;fun(b);// const左值fun(std::move(b));// const右值return 0; }
http://www.hkea.cn/news/14419998/

相关文章:

  • 网站建设怎么支付款项网站建设工作策划方案
  • 烟台网站制作厂家联系方式品牌网络
  • 徐州建站模板公司小说阅读网站开发源码
  • 城固县网站建设wordpress还原站点
  • 校园网站建设意见表填写安徽省建设厅网站个人怎么注册
  • 论坛网站制作费用做新网站推广的活动
  • 郑州旅游网站搭建班级网站建设图片
  • 策勒网站建设新万网
  • 咸宁网站设计公司井陉矿区网站建设
  • 淘宝客单页网站网站设计主要做什么
  • 嘉华伊美网站建设编程培训机构名字
  • 做网站属于程序员吗源码网站代理
  • 企业网站系统详细设计html手机版下载
  • 建设家具网站的目的及功能定位下载什么软件可以做动漫视频网站
  • 在线搭建网站深圳品牌策划vi设计
  • 网站一跳率如何制作单页网站
  • 可信网站注册网站制作合同范本
  • 免费注册网站软件WordPress最强大的主题
  • 商城网站带宽控制玉林做网站公司
  • 在线做头像网站有哪些个人网站备案简介
  • it外包方式包括重庆网站seo昔年优化
  • 龙岗中心城有学网站建设网站建设与管理领导小组
  • 个人网站模板怎么用试用网站cms
  • 做网站哪些做网站开发需要考什么证书
  • 人防工程做资料的网站做网站服务器可以挂到外地么
  • 成都建立网站的公司建设免费网站模板
  • 网站制作与维护公司网站基本建设投资内容
  • 湖北响应式网站建设企业wordpress应用教程 pdf
  • 用手机可以做网站吗wordpress 去掉w
  • 华为商城网站设计分析小锋云主机