瓜子网网站建设策划书/seo网站优化方法

瓜子网网站建设策划书,seo网站优化方法,巩义便宜网站建设费用,cn域名做网站目录 一、右值引用: 1、左值与右值: 2、左值引用和右值引用: 二、右值引用的使用场景: 1、左值引用的使用场景: 2、右值引用的使用场景: 移动构造 移动赋值 三、完美转发: 1、万能引用…

目录

一、右值引用:

1、左值与右值:

2、左值引用和右值引用:

二、右值引用的使用场景:

1、左值引用的使用场景:

2、右值引用的使用场景:

移动构造

移动赋值

三、完美转发:

1、万能引用:

2、实际使用:


一、右值引用:

1、左值与右值:

在了解右值引用前,要先了解什么是左值引用(其实在之前已经使用过很多回了),那么要了解什么是左值引用,就先要了解什么是左值什么是右值

在等号左边的值叫左值吗?在等号右边的值叫右值吗? 

显然定义不会这么简单的,但是左值可以出现赋值符号的左边,右值不能出现在赋值符号左边,也就是说在等号左边的值一定不是右值,在等号右边的可以是左值或右值

左值:

能够进行取地址的操作,也可以被修改

如下的a,b,c都是左值

int main()
{int a = 10;const int b = 10;int* c = new int(0);return 0;
}

右值:

不能够进行取地址的操作,一般不能够被修改

如下,10,x,fmin(x,y)的返回值就是右值

int main()
{double x = 1.1, y = 2.2;//如下就是右值10;x + y;fmin(x, y);return 0;
}

理解:

1、右值的本质是一个临时变量或者常量值
2、这些临时变量是没有被实际存储起来的,所以无法对右值取地址        
3、像上述的fmin的返回值,其实际上就是一份临时拷贝,所以算作右值

2、左值引用和右值引用:

什么是左值引用:

左值引用就是给左值取别名

int main()
{int a = 10;const int b = 10;int* c = new int(0);//这就是左值引用int& pa = a;const int& pb = b;int*& pc = c;return 0;
}

什么是右值引用:

右值引用就是给右值取别名

int main()
{double x = 1.1, y = 2.2;//如下就是右值10;x + y;fmin(x, y);//这个就是右值引用int&& p1 = 10;int&& p2 = x + y;int&& p3 = fmin(x, y);return 0;
}

这里在给右值取别名后,右值会被存储到特定的位置,此时就能够取到该位置的地址了

左值引用可以引用右值吗 ----- 可以

但是,左值引用不能直接引用右值,因为右值不能够被修改,左值可以修改,如果直接引用的话权限会存在放大问题,所以如果想要左值引用右值就需要加上const修饰

像我们之前在函数参数传参的时候经常写const T& x,这就是保证既能够传左值,又能够传右值

template<class T>
void func(const T& val)
{cout << val << endl;
}
int main()
{string s("111");func(s);       //s为左值func("222"); //"222"为右值return 0;
}

右值引用可以引用左值吗 ----- 可以

但是,右值引用也不能直接引用左值,如果想要引用左值,就需要加上move后的左值

int main()
{int a = 10;//右值引用给左值取别名int&& pa = move(a);return 0;
}

为什么加上move后才能让右值引用来引用左值呢?

我们首先要知道,左值引用或者右引用都是在给资源取别名,对于左值引用,就是直接指向原本的数据,对于右值引用,我们知道原本是没有空间资源的,那么右值引用引用右值就是首先开辟一块空间,然后将常量或者临时变量转移到开辟好的地方,然后在指向该地方

所以右值引用的本质是对右值进行资源的转移

此时就有空间资源了,此时就能够取地址了,并且能够对其进行修改了

对于常量,临时变量,表达式的结果这些右值,编译器在右值引用的时候会直接将这些右值进行转移资源,但是对于左值,编译器不敢直接转移,这个时候编译器就为用户提供了一个函数move,当进行move左值的时候,就能够让右值引用 引用左值了

二、右值引用的使用场景:

1、左值引用的使用场景:

左值引用既能够引用左值,又能够引用右值,但是还是存在短板,所以在C++11里面,引入了右值引用来弥补左值引用的短板

在左值引用中:

1、左值引用做参数,防止传参是的拷贝
2、左值引用做返回值,防止返回时对返回对象进行拷贝

首先,写一个自己的string类,在里面写上部分cout来方便打印观察

namespace ppr
{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){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}//拷贝构造函数(现代写法)string(const string& s):_str(nullptr),_size(0),_capacity(0){cout << "string(const string& s) -- 深拷贝" << endl;string tmp;swap(tmp);}//移动构造函数(现代写法)string(string&& s):_str(nullptr), _size(0), _capacity(0){cout << "string(string&& s) -- 移动构造" << endl;swap(s);}//赋值运算符重载(现代写法)string& operator=(const string& s){cout << "string& operator=(const string& s) -- 深拷贝" << endl;string tmp;swap(tmp);return *this;}//析构函数~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}//[]运算符重载char& operator[](size_t i){assert(i < _size);return _str[i];}//改变容量,大小不变void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strncpy(tmp, _str, _size + 1);delete[] _str;_str = tmp;_capacity = n;}}//尾插字符void push_back(char ch){if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_str[_size + 1] = '\0';_size++;}//+=运算符重载string operator+=(char ch){push_back(ch);string tmp(*this);return tmp;}//返回C类型的字符串const char* c_str()const{return _str;}private:char* _str;size_t _size;size_t _capacity;};
}

接着看看左值引用的使用场景

//首先,看看左值引用的使用场景
//值传参
void func1(ppr::string s)
{cout << "void func1(ppr::string s)" << endl;
}
//左值引用传参
void func2(const ppr::string& s)
{cout << "void func2(const ppr::string& s)" << endl;
}int main()
{ppr::string ret1("1111111111111");func1(ret1);//这里采用深拷贝func2(ret1);ret1 += '0';//里面return *this 的时候,也会进行拷贝构造return 0;
}

其中,在func1的时候,传值传参会进行一次拷贝构造,在+=那里,返回* this的时候,也会进行一次拷贝构造这样的话会看到两次深拷贝

左值引用短板:

左值引用能够避免不必要的拷贝构造,但是并不能完全避免

左值引用做参数的时候,能够完全避免传参时的拷贝
左值引用做返回值的时候,不能完全避免拷贝

比如如果返回的是一个局部变量,在返回的时候局部变量被销毁了,此时如果使用左值引用进行返回,就会返回的野指针,此时就不能够用左值引用返回,需要老老实实地值拷贝

如下会进行两次拷贝操作,然后将ret返回

如果在新一点的编译器会进行优化,只需进行一次拷贝操作

如果是引用传参,此时局部变量的局部空间,在出了函数作用域之后就会被释放,此时就会出问题

所以,C++11为了解决这类问题,提出了右值引用来解决这种场景

2、右值引用的使用场景:

右值分为 纯右值将亡值

纯右值:内置类型的右值
将亡值:自定义类型的右值

右值引用和移动语句解决上述问题的方式就是,给当前模拟实现的string类增加移动构造方法

移动构造

移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己

如果没加上述的移动拷贝,就会出现深拷贝

如果加上移动构造,那么就会走移动构造函数,这样就能更加减少拷贝

移动构造的本质就是将参数的右值窃取过来,占为己有,这样它就不用再深度拷贝了,所以叫做移动构造

移动构造和拷贝构造的区别:

1、在没有增加移动构造之前,由于拷贝构造采用的是const左值引用接收参数,因此无论拷贝构造对象时传入的是左值还是右值,都会调用拷贝构造函数
2、增加移动构造之后,由于移动构造采用的是右值引用接收参数,因此如果拷贝构造对象时传入的是右值,那么就会调用移动构造函数
3、string的拷贝构造函数做的是深拷贝,而移动构造函数中只需要调用swap函数进行资源的转移,因此调用移动构造的代价比调用拷贝构造的代价小

左值引用:直接引用对象以减少拷贝

右值引用:间接减少拷贝,将临时资源等将亡值的资源通过 移动构造 进行转移,减少拷贝

移动赋值

移动赋值是一个赋值运算符重载函数,该函数的参数是右值引用类型的,移动赋值也是将传入右值的资源窃取过来,占为己有,这样就避免了深拷贝,之所以它叫移动赋值,就是窃取别人的资源来赋值给自己的意思

// 赋值重载
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;
}

string& operator=(const string& s) 和string& operator=(string&& s) 的区别:

1、在没有string& operator=(string&& s) 的时候,如果进行=操作,那么无论是左值还是右值传参都会调用string& operator=(const string& s) 这个函数

2、在增加移动赋值后,如果是左值就调用原来的函数,如果是右值就调用新加的移动赋值函数

3、移动赋值函数是通过swap函数进行资源的交换,而原来的operator=是通过深拷贝进行,因此,移动赋值的代价比原来的要小

三、完美转发:

1、万能引用:

template<class T>
void PerfectForward(T&& t)
{//...
}

这里函数中的参数并不是右值引用,如果传的模板是左值,这里的参数就是左值引用,相反如果传的模板是右值,那么这里的参数就是右值引用

void func(int& a)
{cout << "左值引用" << endl;
}
void func(const int& a)
{cout << "const 左值引用" << endl;
}
void func(int&& a)
{cout << "右值引用" << endl;
}
void func(const int&& a)
{cout << "const 右值引用" << endl;
}
template<class T>
void perfectForward(T&& val)
{func(val);
}int main()
{int a = 10;perfectForward(a); //左值const int b = 10;  //const 左值perfectForward(b);perfectForward(move(a)); // 右值perfectForward(move(b)); //const 右值return 0;
}

如上,这就是通过func函数重载,来观察编译器会怎样进行函数调用

如上,这是运行结果,为什么会这样呢?难道是编译器做的不对吗,在实际调用中,4个函数没有一个是进入了右值引用,均匹配的是左值引用版本,这是为什么呢?

当对右值进行引用后,会导致右值被存储到特定的位置,此时就能够对这个引用后的右值进行取地址了,这样的话,这个右值就模版被识别成左值了

也就是说,在右值引用过一次后,会导致右值变成左值,但是如果想要继续保证其右值的属性,此时就需要用到完美转发

如上,在对右值引用进行传参的时候,在前面加上forward<T>,这样经过完美转发后,调用PerfectForward函数时传入的是右值就会匹配到右值引用版本的Func函数,传入的是const右值就会匹配到const右值引用版本的Func函数

forward是一个模板函数,需要指定模板参数类型T,确保能正确推导并传递

2、实际使用:

首先实现一个建议的list,在其中实现左值引用的push_back和insert函数

namespace ppr
{template<class T>struct ListNode{T _data;ListNode* _next = nullptr;ListNode* _prev = nullptr;};template<class T>class list{typedef ListNode<T> node;public://构造函数list(){_head = new node;_head->_next = _head;_head->_prev = _head;}//左值引用版本的push_backvoid push_back(const T& x){insert(_head, x);}//右值引用版本的push_backvoid push_back(T&& x){insert(_head, x);}//左值引用版本的insertvoid insert(node* pos, const T& x){node* prev = pos->_prev;node* newnode = new node;newnode->_data = x;prev->_next = newnode;newnode->_prev = prev;newnode->_next = pos;pos->_prev = newnode;}//右值引用版本的insertvoid insert(node* pos, T&& x){node* prev = pos->_prev;node* newnode = new node;newnode->_data = x;prev->_next = newnode;newnode->_prev = prev;newnode->_next = pos;pos->_prev = newnode;}private:node* _head; //指向链表头结点的指针};
}

接着进行左值和右值的push_back版本的调用

int main()
{ppr::list<ppr::string> lt;ppr::string s1("111111111111111");//左值的push_backlt.push_back(s1);cout << endl << endl;ppr::string s2("111111111111111");//右值的push_backlt.push_back(move(s2));cout << endl << endl;lt.push_back("22222222222222222");//右值的push_backreturn 0;
}

但是会发现全部都是深拷贝,这和上述右值被引用后,就可以取地址了,就变成左值了,所以为了避免这种情况,就需要在右值版本的push_back和insert加上完美转发,让右值能够保存右值属性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/73924.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

wx201基于ssm+vue+uniapp的购物系统设计与实现小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…

(二)万字长文解析:deepResearch如何用更长的思考时间换取更高质量的回复?各家产品对比深度详解

DeepResearch的研究背景 业务背景&#xff1a;用更长的等待时间&#xff0c;换取更高质量、更具实用性的结果 当前AI技术发展正经历从“即时响应”到“深度思考”的范式转变。用户对延迟的容忍度显著提升&#xff0c;从传统200ms的交互响应放宽至数秒甚至数分钟&#xff0c;以…

综述速读|086.04.24.Retrieval-Augmented Generation for AI-Generated Content A Survey

论文题目&#xff1a;Retrieval-Augmented Generation for AI-Generated Content: A Survey 论文地址&#xff1a;https://arxiv.org/abs/2402.19473 bib引用&#xff1a; misc{zhao2024retrievalaugmentedgenerationaigeneratedcontent,title{Retrieval-Augmented Generation…

IM腾讯Trtc与vod云点播:实现合流录制并上传,根据参数返回视频地址

全文目录,一步到位 1.前言简介1.1 专栏传送门1.1.1 文档传送门 2. java基础使用2.1 准备工作2.1.1 云控制台获取(密钥和密钥secret)2.1.2 找到trtc控制台2.1.3 vod云点播控制台 2.2 使用准备的数据进行操作2.2.0 引入依赖2.2.1 创建TrtcUtils工具类2.2.2 TrtcReqDTO 录制请求dt…

Linux课程学习一

一.fopen与fclose函数 linux中fopen函数直接用man fopen 去查看 函数原型 FILE * fopen(constchar *path , cost char *mode) /* * description : 打开一个文件 * param ‐ path : 指定文件路径,如&#xff1a;"./test.txt"&#xff0c;也可以直接由文件名 * param …

【区块链安全 | 第十篇】智能合约概述

部分内容与前文互补。 文章目录 一个简单的智能合约子货币&#xff08;Subcurrency&#xff09;示例区块链基础交易区块预编译合约 一个简单的智能合约 我们从一个基础示例开始&#xff0c;该示例用于设置变量的值&#xff0c;并允许其他合约访问它。 // SPDX-License-Identi…

大唐杯02 DTM.PX4.016

01 5G关键技术概述 回传压力大&#xff1a;核心网向基站回传压力大 02 5G关键技术介绍01

docker-compose自定义网络,解决docker-compose网段路由冲突

问题排查 先route一波查看一下路由表 容器路由19和堡垒机路由冲突 解决方案 更改docker网段更改docker生成容器的网段 > 基本操作 docker network ls &#xff1a;查看docker网络列表 docker network inspect <network id/name>&#xff1a;查看某个docker网络详情…

[Mac]利用Hexo+Github Pages搭建个人博客

由于我这台Mac基本没啥环境&#xff0c;因此需要从零开始配置&#xff0c;供各位参考。 注意⚠️&#xff1a;MacBook (M4)使用/bin/zsh作为默认Shell&#xff0c;其对应的配置文件为~/.zshrc 参考文档&#xff1a; HEXO系列教程 | 使用GitHub部署静态博客HEXO | 小白向教程 文…

合规+增效 正也科技携智能营销产品出席中睿论坛

正也科技作为医药数字化领域的标杆企业&#xff0c;受邀参展第二届中睿医健产业企业家年会暨第十三届中睿医药新春论坛&#xff0c;本次论坛以“合力启新程”为主题&#xff0c;吸引了800多位医药健康企业的董事长、总经理参与&#xff0c;并通过主论坛、分论坛、路演等形式探讨…

智能巡检机器人:2025年企业安全运维的“数字哨兵“

文章目录 一、2025年&#xff0c;为什么企业需要智能巡检机器人&#xff1f;二、2025年智能巡检机器人的六大核心价值三、2025行业落地实景1. 电网系统——"巡线鹰"集群作战2. 化工园区——"防爆卫士"全天候守护3. 数据中心——"冷血侦探"精准运…

K8S学习之基础五十一:k8s部署jenkins

k8s部署jenkins 创建nfs共享目录&#xff0c; mkdir -p /data/v2 echo /data/v2 *(rw,no_root_squash) > /etc/exports exportfs -arv创建pv、pvc vi pv.yaml apiVersion: v1 kind: PersistentVolume metadata:name: jenkins-k8s-pv spec:capacity:storage: 1GiaccessMod…

Elasticsearch:人工智能时代的公共部门数据治理

作者&#xff1a;来自 Elastic Darren Meiss 人工智能&#xff08;AI&#xff09;和生成式人工智能&#xff08;GenAI&#xff09;正在迅速改变公共部门&#xff0c;从理论探讨走向实际应用。正确的数据准备、管理和治理将在 GenAI 的成功实施中发挥关键作用。 我们最近举办了…

AT24Cxx移植第三方库到裸机中使用

简介 MCU : STM32F103C8T6 库: HAL库裸机开发 EEPROM : AT24C02, 256Byte容量&#xff0c;I2C接口 电路图 AT24C02 电路图 电路图引用 裸机直接读写 // 写入数据到 EEPROM HAL_StatusTypeDef EEPROM_WriteByte(uint16_t MemAddress, uint8_t Data) {// 发送数据uint8_t …

Processor System Reset IP 核 v5.0(vivado)

这个IP的作用&#xff0c;我的理解是&#xff0c;比普通按键复位更加高效灵活&#xff0c;可以配置多个复位输出&#xff0c;可以配置复位周期。 1、输入信号&#xff1a; 重要的信号有时钟clk信号&#xff0c;一般连接到系统时钟&#xff1b;输入复位信号&#xff0c;一般是外…

3月29日星期六今日早报简报微语报早读

3月29日星期六&#xff0c;农历三月初一&#xff0c;早报#微语早读。 1、全国公立医疗机构自3月31日起全面停止收取门诊预交金&#xff1b; 2、永辉超市“胖东来调改店”已达47家店 一线员工薪酬涨幅50%以上&#xff1b; 3、两孩家庭补10万&#xff0c;三孩家庭补20万&#…

pyinstaller 对 pyexecjs模块打包老会有终端框闪烁

解决办法&#xff1a; 修改 execjs 源代码 具体步骤 1. 在 execjs 源文件中&#xff0c;找到 _external_runtime.py 文件中的以下代码 p Popen(cmd, startupinfostartupinfo, stdinPIPE, stdoutPIPE, stderrPIPE, cwdself._cwd,universal_newlinesTrue)2. 修改为&#xff…

Redis-常用命令

目录 1、Redis数据结构 2、命令简介 2.1、通用命令 DEL EXISTS EXPIRE 2.2、String命令 SET和GET MSET和MGET INCR和INCRBY和DECY SETNX SETEX 2.3、Key的层级结构 2.4、Hash命令 HSET和HGET HMSET和HMGET HGETALL HKEYS和HVALS HINCRBY HSETNX 2.5、List命…

uni-app:指引蒙层

组件说明 指引蒙层组件: 通过id标签,突出对应id中的模块; 可以自定义提示词。 点击任意位置关闭蒙层 效果展示和使用示例 切换id之后的效果: 代码实现 <template><view class="guide-mask" v-if="showMask" @click="hideMask"&g…

大数据Spark(五十五):Spark框架及特点

文章目录 Spark框架及特点 一、Spark框架介绍 二、Spark计算框架具备以下特点 Spark框架及特点 一、Spark框架介绍 Apache Spark 是一个专为大规模数据处理而设计的快速、通用的计算引擎。最初由加州大学伯克利分校的 AMP 实验室&#xff08;Algorithms, Machines, and Pe…