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

北京海淀网站制作公司襄阳seo优化排名

北京海淀网站制作公司,襄阳seo优化排名,旅游网站建设方案简介,哪个网站做美食视频网站前言 本期我们接着继续介绍C11的新特性#xff0c;本期我们介绍的这个新特性是很多人都感觉抽象的语法#xff01;它就是可变的模板参数#xff01; 目录 前言 一、可变的模板参数 1.1可变的参数列表 1.2可变的参数包 1.3可变参数包的解析 • 递归展开解析 • 逗号…前言 本期我们接着继续介绍C11的新特性本期我们介绍的这个新特性是很多人都感觉抽象的语法它就是可变的模板参数 目录 前言 一、可变的模板参数 1.1可变的参数列表 1.2可变的参数包 1.3可变参数包的解析 • 递归展开解析 • 逗号表达式解析 二、emplace系列接口 一、可变的模板参数 1.1可变的参数列表 对于可变参数列表我们在C语言就见过例如最典型的就是 printf / scanf 了 我们在使用的时候需要指定类型将不同类型/数量的类型都可以传递过去 int main() {int a;double b;char c;printf(请输入一个整数、一个浮点数和一个字符: );scanf(%d %lf %c, a, b, c);printf(输入了: %d %lf %c\n, a, b, c);return 0; } 1.2可变的参数包 C98/03类模板和函数模板中只能含固定的模板参数C11引入了可变的模板参数能够让你创建接受可变参数的函数模板和类模板这无疑是一个巨大的改进正是改变巨大所以这块比较抽象也比较晦涩难懂本博客主要介绍的是函数模板的可变参数 先来见一见基本的可变参数的函数模板 template class ...Args void ShowList(Args... args) {// ... } 此时我们就可以给这个函数模板传递任意类型、任意个数的参数把这个前面带 ... 的参数统称为参数包Args是模板的参数包args是函数形参的参数包Args... args的个数是0~N个 一般为了提高传递参数的效率可变参数的类型一般会被写成万能引用引用折叠的形式 template class ...Args void ShowList(Args... args) {// ... } 由于可变模板的参数是可变的即支持任意类型、任意数量的参数所以可以这样写 int main() {ShowList(1);ShowList(1, a, 9.9);ShowList(1, aaa, 9.9, b);ShowList(std::vectorint(), std::listdouble(), zzz, 999, aaaaaaa);return 0; } 这也体现了可变模板参数的强大 1.3可变参数包的解析 用可变参数的人爽了但是解析参数包的过程其实是不简单的下面是一种非常典型的错误栗子 templateclass ...Args void showList(Args... args) {// 错误的解析参数方式int n sizeof...(args);for (int i 0; i n; i){// 获取具体的可变参数args[i];} }这里使用sizeof获取参数包args的大小是把...放到了args的前面第一次看起来的时候有点别扭~个人感觉 这种方式是符合我们的直觉的但是他是错的 这里简单理解就是编译器不支持这样写sizeof是编译时操作符而参数包不是和数组一样连续的所以不可用下标访问 • 递归展开解析 void ShowList() { cout endl; }// 用于结束递归templateclass T, class ...Args void ShowList(const T t, Args ...args) {cout t ;ShowList(args...); } 这里他是如何做的呢我用一个简单的例子第三个来画一下 也就是编译器在编译期间将上述的函数模板实例化成了很多的实例在运行时进行了调用 • 逗号表达式解析 除了上述递归的展开的方式解析参数包以外还有一种直接展开的方式就是用逗号表达式解析具体如下 templateclass T void Print(T t) {cout t endl; }templateclass ...Args void ShowList(Args... args) {int arr[] { (Print(args), 0)... };cout endl; } OK编译后他就是这个样子 templateclass ...Args void ShowList(Args... args) {int arr[] { (Print(1), 0), (Print(a), 0), (Print(9,9), 0)};cout endl; } 为什么这里要写成 (Print(args), 0)... 呢 我们知道逗号表达式的结果是最后一项的值这是主要是在展开的同时给arr数组赋值 二、emplace系列接口 C11 也在STL中引入了可变的模板参数这一批接口被称为emlpace系列的接口/函数 这里以list为例进行介绍 为了方便演示我们玩还是使用我们前几期用的cp::string所以我们把他给拿过来 namespace cp {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};cp::string to_string(int value){cp::string str;bool flag true;if (value 0){flag false;value 0 - value;}while (value 0){int x value % 10;value / 10;str (0 x);}if (flag false){str -;}std::reverse(str.begin(), str.end());return str;} } listcp::string lt; // 分别让emplace_back和push_back都插入一个 左值 对象 cp::string s1(hello); cout ------------------------------- endl; lt.push_back(s1); cout endl; lt.emplace_back(s1);// 分别让emplace_back和push_back都插入一个 左值move后的 对象 cout ------------------------------- endl; lt.push_back(move(s1)); cout endl; lt.emplace_back(move(s1));// 分别让emplace_back和push_back都插入一个 右值 对象 cout ------------------------------- endl; lt.push_back(cp::string(6666)); cout endl; lt.emplace_back(cp::string(6666));// 分别让emplace_back插入一个参数包 push_back都插入一个右值 对象 cout ------------------------------- endl; lt.push_back(6666); cout endl; lt.emplace_back(6666); 看结果 通过上面的栗子我们可以得出结论 1、当emplace和push系列都插入左值/move(左值)的结果是一样的拷贝构造/移动构造 2、当emplace插入一个参数包push系列都插入一个右值时emplace是构造而push系列是构造移动构造 • 为什么emplace系列传入参数包后是直接构造 上面介绍了emplace系列的是引用了模板的可变参数所以他可以接受的是一个参数包其实他的底层是一层层的传递下去直接到构造那里用参数包的参数直接构造的所以就只有一次构造 这其实就是有人所说的emplace效率高的原因所在就是直接使用emplace传递参数包可以少一次移动构造 所以emplace系列的插入对象的优先级为 参数包 右值 左值 这里左值的代价较高因为有一次的拷贝构造右值其实和参数包的差别也还好原因是移动构造的待见很轻但是能用参数包的地方还是用参数包以后就建议多使用emplace系列因为emplace系列push系列 的效率 OK好兄弟本期分享就到这里我是cp我们下期再见~
http://www.dnsts.com.cn/news/25138.html

相关文章:

  • 经典网站设计欣赏淘宝刷单网站建设
  • 一个网站如何优化凡客设计
  • 响应式网站和自适应网站区别环境设计排版哪个网站好
  • 励志网站源码网站建设一条龙
  • 网站建设管理总结华为手机一键优化
  • 网站建设与制wordpress不使用缩略图
  • 建瓯市建设银行网站怎么用dw做地图网站
  • 网站建设导航栏设计wordpress 视频 广告
  • 在国际网站上做贸易怎么发货工业风 网站建设
  • 建设网站需要的软硬件wordpress 付费
  • 开互联网公司网站是自己建吗钓鱼网站在线生成
  • 织梦猫html5高端网络服务机构网站模板西安seo外包价格
  • 网站备案地址深圳建网建网站
  • 深圳网站建设代理大连市城乡建设厅网站
  • 公司网站域名备案流程做暧暧的网站
  • 帮人做logo网站广告设计与制作是干什么的
  • 国内大型网站制作wordpress添加按钮
  • 怎么给网站做后台简洁网站模板下载
  • 上海网站开发团队厦门35网站建设公司
  • 邯郸企业建网站现在电商做的设计用的什么网站
  • 长春高铁站怎么把网站模板上传到自己的网站
  • 网站右边上下浮动代码曼联对利物浦新闻
  • 个人做网站流程吐鲁番seo快速排名
  • 免费做效果图的网站有哪些顺德网站优化
  • 山东网站备案时间wordpress二维码用户登录
  • 做传销网站的桂林象鼻山景区简介
  • 做it软件的网站公司部门新年祝福语简短
  • 网站浏览历史能恢复吗怎么设置的青岛企业建设网站公司
  • 下载的网站模板怎么用辽宁网站seo
  • 加强公司门户网站建设电脑做apk的网站h5