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

慧谷网站开发文档成都的网站建设

慧谷网站开发文档,成都的网站建设,网络广告策划书模板范文,做网站用linux哪个版本目录 1、什么是左值引用和右值引用2、左值引用与右值引用比较3、右值引用使用场景和意义4、右值引用引用左值的分析5、完美转发 1、什么是左值引用和右值引用 传统的C语法中就有引用的语法#xff0c;而C11中新增了的右值引用语法特性#xff0c;所以从现在开始我们之前学习… 目录 1、什么是左值引用和右值引用2、左值引用与右值引用比较3、右值引用使用场景和意义4、右值引用引用左值的分析5、完美转发 1、什么是左值引用和右值引用 传统的C语法中就有引用的语法而C11中新增了的右值引用语法特性所以从现在开始我们之前学习的引用就叫做左值引用。无论左值引用还是右值引用都是给对象取别名。 左值是一个表示数据的表达式(如变量名或解引用的指针)我们可以获取它的地址可以对它赋值左值可以出现赋值符号的左边右值不能出现在赋值符号左边。定义时const修饰符后的左值不能给他赋值但是可以取它的地址。左值引用就是给左值的引用给左值取别名。 例子 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; }右值也是一个表示数据的表达式如字面常量、表达式返回值函数返回值(这个不能是左值引用返回)等等右值可以出现在赋值符号的右边但是不能出现出现在赋值符号的左边右值不能取地址。右值引用就是对右值的引用给右值取别名。 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; }需要注意的是右值是不能取地址的但是给右值取别名后会导致右值被存储到特定位置且可以取到该位置的地址例如不能取字面量10的地址但是rr1引用后可以对rr1取地址也可以修改rr1。如果不想rr1被修改可以用const int rr1 去引用是不是感觉很神奇这个了解一下实际中右值引用的使用场景并不在于此这个特性也不重要。 int main() {double x 1.1, y 2.2;int rr1 10;const double rr2 x y;rr1 20;rr2 5.5; // 报错return 0; }2、左值引用与右值引用比较 左值引用总结 左值引用只能引用左值不能引用右值。但是const左值引用既可引用左值也可引用右值 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; }右值引用总结 右值引用只能右值不能引用左值。但是右值引用可以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; }3、右值引用使用场景和意义 前面我们可以看到左值引用既可以引用左值和又可以引用右值那为什么C11还要提出右值引用呢是不是化蛇添足呢下面我们来看看左值引用的短板右值引用是如何补齐这个短板的 namespace hxj {class string{public:typedef char* iterator;iterator begin(){return _str;}iterator end(){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);}// s1.swap(s2)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;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(string s):_str(nullptr), _size(0), _capacity(0){cout string(string s) -- 移动语义 endl;swap(s);}// 移动赋值string operator(string s){cout string operator(string s) -- 移动语义 endl;swap(s);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)string operator(char ch){push_back(ch);return *this;}const char* c_str() const{return _str;}private:char* _str;size_t _size;size_t _capacity; // 不包含最后做标识的\0}; }左值引用的使用场景做参数和做返回值都可以提高效率 void func1(hxj::string s) {} void func2(const hxj::string s) {} int main() {hxj::string s1(hello world);// func1和func2的调用我们可以看到左值引用做参数减少了拷贝提高效率的使用场景和价值func1(s1);func2(s1);// string operator(char ch) 传值返回存在深拷贝// string operator(char ch) 传左值引用没有拷贝提高了效率s1 !;return 0; }左值引用的短板 但是当函数返回对象是一个局部变量出了函数作用域就不存在了就不能使用左值引用返回只能传值返回。例如hxj::string to_string(int value)函数中可以看到这里只能使用传值返回传值返回会导致至少1次拷贝构造(如果是一些旧一点的编译器可能是两次拷贝构造) namespace hxj {hxj::string to_string(int value){bool flag true;if (value 0){flag false;value 0 - value;}hxj::string str;while (value 0){int x value % 10;value / 10;str (0 x);}if (flag false){str -;}std::reverse(str.begin(), str.end());return str;} } int main() {// 在hxj::string to_string(int value)函数中可以看到这里// 只能使用传值返回传值返回会导致至少1次拷贝构造(如果是一些旧一点的编译器可能是两次拷贝构造)。hxj::string ret1 hxj::to_string(1234);hxj::string ret2 hxj::to_string(-1234);return 0; }右值引用和移动语义解决上述问题 在hxj::string中增加移动构造移动构造本质是将参数右值的资源窃取过来占位已有那么就不用做深拷贝了所以它叫做移动构造就是窃取别人的资源来构造自己。 // 移动构造 string(string s):_str(nullptr), _size(0), _capacity(0) {cout string(string s) -- 移动语义 endl;swap(s); } int main() {hxj::string ret2 hxj::to_string(-1234);return 0; }再运行上面hxj::to_string的两个调用我们会发现这里没有调用深拷贝的拷贝构造而是调用了移动构造移动构造中没有新开空间拷贝数据所以效率提高了。 不仅仅有移动构造还有移动赋值 在hxj::string类中增加移动赋值函数再去调用hxj::to_string(1234)不过这次是将hxj::to_string(1234)返回的右值对象赋值给ret1对象这时调用的是移动构造。 // 移动赋值 string operator(string s) {cout string operator(string s) -- 移动语义 endl;swap(s);return *this; } int main() {hxj::string ret1;ret1 hxj::to_string(1234);return 0; } // 运行结果 // string(string s) -- 移动语义 // string operator(string s) -- 移动语义这里运行后我们看到调用了一次移动构造和一次移动赋值。因为如果是用一个已经存在的对象接收编译器就没办法优化了。hxj::to_string函数中会先用str生成构造生成一个临时对象但是我们可以看到编译器很聪明的在这里把str识别成了右值调用了移动构造。然后在把这个临时对象做为hxj::to_string函数调用的返回值赋值给ret1这里调用的移动赋值。 STL中的容器都是增加了移动构造和移动赋值 4、右值引用引用左值的分析 按照语法右值引用只能引用右值但右值引用一定不能引用左值吗因为有些场景下可能真的需要用右值去引用左值实现移动语义。当需要用右值引用引用一个左值时可以通过move函数将左值转化为右值。 C11中std::move()函数位于 头文件中该函数名字具有迷惑性它并不搬移任何东西唯一的功能就是将一个左值强制转化为右值引用然后实现移动语义。 templateclass _Ty inline typename remove_reference_Ty::type move(_Ty _Arg) _NOEXCEPT {return ((typename remove_reference_Ty::type)_Arg); } int main() {hxj::string s1(hello world);// 这里s1是左值调用的是拷贝构造hxj::string s2(s1);// 这里我们把s1 move处理以后, 会被当成右值调用移动构造// 但是这里要注意一般是不要这样用的因为我们会发现s1的// 资源被转移给了s3s1被置空了。hxj::string s3(std::move(s1));return 0; }STL容器插入接口函数也增加了右值引用版本 void push_back(value_type val); int main() {listhxj::string lt;hxj::string s1(1111);// 这里调用的是拷贝构造lt.push_back(s1);// 下面调用都是移动构造lt.push_back(2222);lt.push_back(std::move(s1));return 0; } 运行结果 // string(const string s) -- 深拷贝 // string(string s) -- 移动语义 // string(string s) -- 移动语义5、完美转发 模板中的 万能引用 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; } // 模板中的不代表右值引用而是万能引用其既能接收左值又能接收右值。 // 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力 // 但是引用类型的唯一作用就是限制了接收的类型后续使用中都退化成了左值 // 我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用我们下面学习的完美转发 templatetypename T void PerfectForward(T t) {Fun(t); } int main() {PerfectForward(10); // 右值int a;PerfectForward(a); // 左值PerfectForward(std::move(a)); // 右值const int b 8;PerfectForward(b); // const 左值PerfectForward(std::move(b)); // const 右值return 0; }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; } // std::forwardT(t)在传参的过程中保持了t的原生类型属性。 templatetypename T void PerfectForward(T t) {Fun(std::forwardT(t)); } int main() {PerfectForward(10); // 右值int a;PerfectForward(a); // 左值PerfectForward(std::move(a)); // 右值const int b 8;PerfectForward(b); // const 左值PerfectForward(std::move(b)); // const 右值return 0; }完美转发实际中的使用场景 templateclass T struct ListNode {ListNode* _next nullptr;ListNode* _prev nullptr;T _data; }; templateclass T class List {typedef ListNodeT Node; public:List(){_head new Node;_head-_next _head;_head-_prev _head;}void PushBack(T x){//Insert(_head, x);Insert(_head, std::forwardT(x));}void PushFront(T x){//Insert(_head-_next, x);Insert(_head-_next, std::forwardT(x));}void Insert(Node* pos, T x){Node* prev pos-_prev;Node* newnode new Node;newnode-_data std::forwardT(x); // 关键位置// prev newnode posprev-_next newnode;newnode-_prev prev;newnode-_next pos;pos-_prev newnode;}void Insert(Node* pos, const T x){Node* prev pos-_prev;Node* newnode new Node;newnode-_data x; // 关键位置// prev newnode posprev-_next newnode; newnode-_prev prev;newnode-_next pos;pos-_prev newnode;} private:Node* _head; }; int main() {Listhxj::string lt;lt.PushBack(1111);lt.PushFront(2222);return 0; }
http://www.dnsts.com.cn/news/251079.html

相关文章:

  • 仿站工具在线一个wordpress程序搭建多个网站
  • 广东平台网站建设找哪家深圳专业企业网站建
  • 网站免费网站免费优化优化wordpress社区
  • 杭州广众建设工程有限公司网站做网站怎么接广告赚钱吗
  • 网站建设实用的网站企业网页制作平台
  • 唐山网站建设公司网页截图快捷键
  • 网站网络营销石家庄品牌网站建设
  • 百度站长如何验证网站帝国cms做中英文网站
  • 修文县生态文明建设局网站wordpress客户留言插件
  • 襄阳 网站建设快速排名seo
  • 医院建设网站意义.mil 域名网站有哪些
  • 是先做网站还是先备案安居客网站是用什么程序做的
  • 杨浦网站建设 网站外包课程网站建设
  • jsp怎么做购物网站专业seo整站优化
  • 网站制作工具有哪些绍兴优秀做网站的
  • 做视频网站的备案要求吗网站建设咨询有客诚信
  • 有哪些专门做创意门头的网站京津冀协同发展10周年
  • 网站备案拍布幕南平网站建设公司
  • 常德论坛网站wordpress 正在执行维护
  • 尖扎县公司网站建设做班级网站的目的
  • 湖南省建设部网站app图片怎么制作
  • 精品资料网官方网站清爽网站模板
  • 网站调优技能哪一个景区网站做的最成熟
  • 哪个网站做动图wordpress 插件配置
  • vvic一起做网站wordpress建站软件
  • 四川省建设局网站宝塔面板怎么做自己的网站
  • 0基础建站教程wordpress 木马
  • 上海个人网站备案企业网站建设硬件
  • 网站目录有什么意义广西城乡和建设厅网站
  • 网站被模仿怎么办简易广州网站建设