C++11编译器优化以及引用折叠

1.左值与右值的意义

1.左值引用和右值引用最终目的是减少拷贝,提高效率

2.左值引用还可以修改参数/返回值

左值引用不足:

部分函数放回场景,只能传值返回,不能引用左值返回

当前函数局部对象,出了当前函数作用域生命周期到了,就销毁了,不能引用左值引用返回,只能传值返回

解决方案一:不用返回值,用输出型参数(牺牲可读性)

解决方案二:编译器优化

解决方案三:右值引用和移动语义

2.右值对象构造,只有拷贝构造,没有移动构造的场景

下图第一个是在Linux下用指令实现的不优化的场景,先是参数的传过去发生构造,然后把形参进行拷贝构造,俩个参数会有俩次,而后是返回值要拷贝给临时变量有一次拷贝构造,临时变量给ret又会发生拷贝构造。

第二个是1代优化,编译器会有优化,把构造和拷贝构造合成构造,企鹅在返回时不生成临时变量,直接给ret拷贝构造。

第三个是二代优化,连临时变量都不生成,把ret对象的引用传过去,大大提高了效率。

对于赋值的情况

第一个是无优化情况,是先拷贝给临时变量然后在拷贝复制给ret

第二个是一代优化的情况,跟无优化的一样

第三个是二代优化,可以看到只剩拷贝赋值了,把拷贝构造和拷贝赋值合成一个,生成的临时变量是返回对象的引用,就可以减少拷贝构造了

 

 

3.有移动构造和移动赋值后

不优化情况,虽然有很多的移动构造存在,但是移动构造的代价很少

一代优化情况下,就是直接返回值对ret进行移动构造,不要临时变量

二代优化情况下,就是str是ret对象的引用,就不会有俩次移动构造

有赋值情况下

不优化情况下是有构造,移动构造和移动赋值

一代优化情况下和不优化是一样的

二代优化是把str变成临时变量的引用,这样就可以省略掉移动构造,这里的临时对象是会有一次构造的

 

 

 

 4.引用折叠

C++中不能直接定义引用的引用如int& && r=i;这样写会报错,通过模板或typedef中的类型操作可以构成引用的引用。

通过模板或typedef中的类型操作构成引用时,这时C++11给出了一个引用折叠的规矩:右值引用的右值引用折叠成右值引用,其它组合都是左值引用。

示例代码

// 由于引用折叠限定,f1实例化以后总是一个左值引用
template<class T>
void f1(T& x)
{}// 由于引用折叠限定,f2实例化后可以是左值引用,也可以是右值引用
template<class T>
void f2(T&& x)
{}int main()
{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&&// 没有折叠->实例化为void f1(int& x)f1<int>(n);//f1<int>(0); // 报错// 折叠->实例化为void f1(int& x)f1<int&>(n);//f1<int&>(0); // 报错// 折叠->实例化为void f1(int& x)f1<int&&>(n);//f1<int&&>(0); // 报错// 折叠->实例化为void f1(const int& x)f1<const int&>(n);f1<const int&>(0);// 折叠->实例化为void f1(const int& x)f1<const int&&>(n);f1<const int&&>(0);// 没有折叠->实例化为void f2(int&& x)//f2<int>(n); // 报错f2<int>(0);// 折叠->实例化为void f2(int& x)f2<int&>(n);//f2<int&>(0); // 报错// 折叠->实例化为void f2(int&& x)//f2<int&&>(n); // 报错f2<int&&>(0);return 0;
}

万能引用

既可以变成左值引用也可以变成右值引用

 万能引用 
template<class T>
void Function(T&& t)
{int a = 0;T x = a;//x++;cout << &a << endl;cout << &x << endl << endl;
}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;// b是左值,推导出T为const int&,引用折叠,模板实例化为void Function(const int& t)// 所以Function内部会编译报错,x不能++//Function(b);    // const 左值// std::move(b)右值,推导出T为const int,模板实例化为void Function(const int&& t)// 所以Function内部会编译报错,x不能++Function(std::move(b)); // const 右值return 0;
}

5.完美转发

function(T&& t)函数模板中,传左值实例化后是左值引用的function函数,传右值实例化以后是右值引用的function函数

前面知识可知,变量表达式都是左值属性,也就意味着一个右值被右值引用绑定后,右值引用变量表达式的属性是左值,在function函数中t的属性是左值,那么把t传递下一层函数,这时匹配的就是左值引用的版本的函数,要保证t对象的属性,就需要使用完美转发来来实现。

代码示例

foword<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; }template < class T>
void Function(T&& t)
{Fun(forward<T>(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);// std::move(b)右值,推导出T为const int,模板实例化为void Function(const int&&t)Function(std::move(b)); // const 右值return 0;
}

6.补充

Lish.h

#pragma once
#include<assert.h>//#include"Iterator.h"namespace bit
{template<class T>struct list_node{T _data;list_node<T>* _next;list_node<T>* _prev;/*list_node(const T& data = T()):_data(data),_next(nullptr),_prev(nullptr){}list_node(T&& data):_data(forward<T>(data)), _next(nullptr), _prev(nullptr){}*/list_node() = default;template<class X>list_node(X&& data):_data(forward<X>(data)), _next(nullptr), _prev(nullptr){}};template<class T, class Ref, class Ptr>struct list_iterator{typedef list_node<T> Node;typedef list_iterator<T, Ref, Ptr> Self;Node* _node;list_iterator(Node* node):_node(node){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}Self& operator++(){_node = _node->_next;return *this;}Self& operator--(){_node = _node->_prev;return *this;}Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}Self& operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const Self& s) const{return _node != s._node;}bool operator==(const Self& s) const{return _node == s._node;}};/*template<class T>struct list_const_iterator{typedef list_node<T> Node;typedef list_const_iterator<T> Self;Node* _node;list_const_iterator(Node* node):_node(node){}const T& operator*(){return _node->_data;}const T* operator->(){return &_node->_data;}Self& operator++(){_node = _node->_next;return *this;}Self& operator--(){_node = _node->_prev;return *this;}Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}Self& operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const Self& s) const{return _node != s._node;}bool operator==(const Self& s) const{return _node == s._node;}};*/template<class T>class list{typedef list_node<T> Node;public:/*typedef list_iterator<T> iterator;typedef list_const_iterator<T> const_iterator;*/typedef list_iterator<T, T&, T*> iterator;typedef list_iterator<T, const T&, const T*> const_iterator;//typedef ReverseIterator<iterator, T&, T*> reverse_iterator;//typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;//reverse_iterator rbegin()//{//	return reverse_iterator(--end());//}//reverse_iterator rend()//{//	return reverse_iterator(end());//}// 对称/*	reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}const_reverse_iterator rbegin() const{return const_reverse_iterator(end());}const_reverse_iterator rend() const{return const_reverse_iterator(begin());}*/iterator begin(){return _head->_next;}iterator end(){return _head;}const_iterator begin() const{return _head->_next;}const_iterator end() const{return _head;}void empty_init(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}list(){empty_init();}list(initializer_list<T> il){empty_init();for (auto& e : il){push_back(e);}}// lt2(lt1)list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}// lt1 = lt3list<T>& operator=(list<T> lt){swap(lt);return *this;}~list(){clear();delete _head;_head = nullptr;}void clear(){auto it = begin();while (it != end()){it = erase(it);}}// 16:18继续void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}/*void push_back(const T& x){insert(end(), x);}void push_back(T&& x){insert(end(), forward<T>(x));}*/// 万能引用template<class X>void push_back(X&& x){insert(end(), forward<X>(x));}void push_front(const T& x){insert(begin(), x);}//iterator insert(iterator pos, const T& x)//{//	Node* cur = pos._node;//	Node* prev = cur->_prev;//	Node* newnode = new Node(x);//	// prev newnode cur//	newnode->_next = cur;//	cur->_prev = newnode;//	newnode->_prev = prev;//	prev->_next = newnode;//	++_size;//	return newnode;//}//iterator insert(iterator pos, T&& x)//{//	Node* cur = pos._node;//	Node* prev = cur->_prev;//	Node* newnode = new Node(forward<T>(x));//	// prev newnode cur//	newnode->_next = cur;//	cur->_prev = newnode;//	newnode->_prev = prev;//	prev->_next = newnode;//	++_size;//	return newnode;//}template<class X>iterator insert(iterator pos, X&& x){Node* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(forward<X>(x));// prev newnode curnewnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;prev->_next = newnode;++_size;return newnode;}void pop_back(){erase(--end());}void pop_front(){erase(begin());}iterator erase(iterator pos){assert(pos != end());Node* prev = pos._node->_prev;Node* next = pos._node->_next;prev->_next = next;next->_prev = prev;delete pos._node;--_size;return next;}size_t size() const{return _size;}bool empty() const{return _size == 0;}private:Node* _head;size_t _size;};struct AA{int _a1 = 1;int _a2 = 1;};按需实例化T* const ptr1const T* ptr2//template<class Container>//void print_container(const Container& con)//{//	// const iterator -> 迭代器本身不能修改//	// const_iterator -> 指向内容不能修改//	typename Container::const_iterator it = con.begin();//	//auto it = con.begin();//	while (it != con.end())//	{//		//*it += 10;//		cout << *it << " ";//		++it;//	}//	cout << endl;//	for (auto e : con)//	{//		cout << e << " ";//	}//	cout << endl;//}}

test.cpp

#define _CRT_SECURE_NO_WARNINGS 1#include<vector>
#include<iostream>
#include<map>
#include<string>
#include<assert.h>
using namespace std;
#include<list>
#include"Lish.h"namespace bit
{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);}// 拷贝构造string(const string& s):_str(nullptr){cout << "string(const string& s) -- 拷贝构造" << endl;reserve(s._capacity);for (auto ch : s){push_back(ch);}}void swap(string& ss){::swap(_str, ss._str);::swap(_size, ss._size);::swap(_capacity, ss._capacity);}// 移动构造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;};
}class Solution {
public:// 传值返回需要拷贝bit::string addStrings(bit::string num1, bit::string num2) {bit::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 << &str << endl;return str;}
};int main()
{bit::list<bit::string> lt;bit::string s1("11111111111");lt.push_back(s1);bit::string s2("33333333333");lt.push_back(move(s2));lt.push_back("22222222222");}

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

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

相关文章

小程序学习06——uniapp组件常规引入和easycom引入语法

目录 一 组件注册 1.1 组件全局注册 1.2 组件全局引入 1.3 组件局部引入 页面引入组件方式 1.3.1 传统vue规范&#xff1a; 1.3.2 通过uni-app的easycom 二 组件的类型 2.1 基础组件列表 一 组件注册 1.1 组件全局注册 &#xff08;a&#xff09;新建compoents文件…

【时时三省】(C语言基础)常见的动态内存错误2

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 对非动态开辟空间内存使用free释放 示例&#xff1a; 这个arr数组是在栈上的 *p指向的就是arr 对非动态空间也用了free ferr只能在动态开辟空间使用 使用free释放一块动态开辟空间的一部分…

3D高斯点云CUDA版本数据制作与demo运行

0. 简介 关于UCloud(优刻得)旗下的compshare算力共享平台 UCloud(优刻得)是中国知名的中立云计算服务商&#xff0c;科创板上市&#xff0c;中国云计算第一股。 Compshare GPU算力平台隶属于UCloud&#xff0c;专注于提供高性价4090算力资源&#xff0c;配备独立IP&#xff0c;…

【游戏设计原理】46 - 魔杖

幻想&#xff0c;人们可以通过多种形式来引发&#xff0c;比如文字&#xff0c;图片&#xff0c;绘画&#xff0c;语言等&#xff0c;但游戏与以上这些形式的区别&#xff0c;正如游戏与其他艺术形式的区别一样&#xff0c;游戏作为一种艺术和娱乐形式&#xff0c;其独特之处在…

基于Java的敬老院管理系统的设计和实现【源码+文档+部署讲解】

基于Java的敬老院管理系统设计和实现 摘 要 新世纪以来,互联网与计算机技术的快速发展,我国也迈进网络化、集成化的信息大数据时代。对于大众而言,单机应用早已成为过去&#xff0c;传统模式早已满足不了当下办公生活等多种领域的需求,在一台电脑上不联网的软件少之又少&#x…

Git快速入门(一)·Git软件的安装以及GitHubDesktop客户端的安装

目录 1. 概述 1.1 版本控制介绍 1.1.1 集中式版本控制 1.1.2 分布式版本控制 1.1.3 多人协作开发 2. 安装Git 3. 安装GitHubDesktop客户端 1. 概述 Git 是一个免费的、开源的分布式版本控制系统。它能够快速高效地处理从小型到大型的各种项目。Git 具有易于学习…

数据挖掘——神经网络分类

神经网络分类 神经网络分类人工神经网络多层人工神经网络 误差反向传播&#xff08;BP&#xff09;网络后向传播算法 神经网络分类 人工神经网络 人工神经网络主要由大量的神经元以及它们之间的有向连接构成。包含三个方面&#xff1a; 神经元的激活规则 主要是指神经元输入…

PDF文件提示-文档无法打印-的解决办法

背景信息 下载了几个签名的PDF文件&#xff0c;想要打印纸质版&#xff0c;结果打印时 Adobe Acrobat Reader 提示【文档无法打印】: 解决办法 网上的方案是使用老版本的PDF阅读器&#xff0c; 因为无法打印只是一个标识而已。 PDF文件不能打印的五种解决方案-zhihu 这些方…

docker容器间基于bridge双向通信

前面介绍了通过link实现容器间的单向通信&#xff1a; docker容器间基于Link单向通信-CSDN博客 情景概述 通过前面已经知道了设置link来达到容器间通过容器名称双向通信&#xff0c;那是不是可以通过每个容器都设置link来达到双向通信&#xff0c;这种方式实现起来太麻烦&…

前端如何判断多个请求完毕

在前端开发中&#xff0c;经常会遇到需要同时发起多个异步请求&#xff0c;并在所有请求都完成后再进行下一步操作的情况。 这里有几个常用的方法来实现这一需求&#xff1a; 使用 Promise.all() Promise.all() 方法接收一个 Promise 对象的数组作为参数&#xff0c;当所有的…

云备份项目--服务端编写

文章目录 7. 数据管理模块7.1 如何设计7.2 完整的类 8. 热点管理8.1 如何设计8.2 完整的类 9. 业务处理模块9.1 如何设计9.2 完整的类9.3 测试9.3.1 测试展示功能 完整的代码–gitee链接 7. 数据管理模块 TODO: 读写锁&#xff1f;普通锁&#xff1f; 7.1 如何设计 需要管理…

exam0-试卷整理

exam0-试卷整理 2010&#xff0c;2013是梦开始的地方&#xff0c;大概率会出原题的 2010 2013 2015 大题 manchester RIP更新 说出ISO与TCP/IP模型的相同点和不同点&#xff08;8分&#xff09; 相似&#xff1a; 两者都有层次&#xff0c;网络专业人员都需要知道二者&a…

ACL---访问控制列表---策略

在路由器流量流入或者流出的接口上匹配流量&#xff0c;之后执行设定好的动作---permit&#xff08;允许&#xff09;deny&#xff08;拒绝&#xff09; 1.访问控制&#xff1a; 在路由器流量流入或者流出的接口上匹配流量&#xff0c;之后执行设定好的动作---permit&#xf…

element输入框及表单元素自定义前缀

如图所示&#xff1a; <el-input class"custom-input" placeholder"请输入" prefix-icon"prefix" v-model"form.name" clearable></el-input> :deep(.custom-input) {.el-input__icon {display: inline-block;width: 40…

C#调用Lua

目录 xLua导入 打包工具导入 单例基类导入与AB包管理器导入 Lua解析器 文件加载与重定向 Lua解析器管理器 全局变量获取 全局函数获取 对于无参数无返回值 对于有参数有返回值 对于多返回值 对于变长参数 完整代码 List与Dictionary映射Table 类映射Table 接口映射…

渗透测试-非寻常漏洞案例

声明 本文章所分享内容仅用于网络安全技术讨论&#xff0c;切勿用于违法途径&#xff0c;所有渗透都需获取授权&#xff0c;违者后果自行承担&#xff0c;与本号及作者无关&#xff0c;请谨记守法. 此文章不允许未经授权转发至除先知社区以外的其它平台&#xff01;&#xff0…

node.js之---事件循环机制

事件循环机制 Node.js 事件循环机制&#xff08;Event Loop&#xff09;是其核心特性之一&#xff0c;它使得 Node.js 能够高效地处理大量并发的 I/O 操作。Node.js 基于 非阻塞 I/O&#xff0c;使用事件驱动的模型来实现异步编程。事件循环是 Node.js 实现异步编程的基础&…

基于深度学习的视觉检测小项目(二) 环境和框架搭建

一、环境和框架要求 SAM的环境要求&#xff1a; Python>3.7 PyTorch>1.7 torchvision>0.8 YOLO V8的环境要求&#xff1a;YOLO集成在ultralytics库中&#xff0c;ultralytics库的环境要求&#xff1a; Python>3.7 PyTorch>1.10.0 1、确定pytorch版本…

MySQL 06 章——多表查询

多表查询&#xff0c;也称为关联查询&#xff0c;是指两个表或多个表一起完成查询操作 前提条件&#xff0c;这些一起查询的表之间是有关系的&#xff08;一对一、一对多&#xff09;&#xff0c;它们之间一定是有关联字段的。这个关联字段可能建立了外键&#xff0c;也可能没…

Web前端基础知识(五)

盒子模型 盒子模型是CSS中一种常用于布局的基本概念。描述了 文档中的每个元素都可以看成是一个矩形的盒子&#xff0c;包含了内容、内边距、文本边距、外边距。 ---------------------------------------------------------------------------------------------------------…