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

设计签名的小程序站长之家seo综合查询

设计签名的小程序,站长之家seo综合查询,网站建设报价方案对比,海外直播C11特性梳理 1. 列表初始化2. auto & decltype3. 右值引用3.1. 左右值引用比较3.2. 右值引用的意义3.3. 万能引用与完美转发3.4. 移动构造与移动赋值 4. default & delete5. 可变参数模板6. push_back 与 emplace_back7. lambda表达式7.1. 捕捉列表 8. function包装器8…

C++11特性梳理

  • 1. 列表初始化
  • 2. auto & decltype
  • 3. 右值引用
    • 3.1. 左右值引用比较
    • 3.2. 右值引用的意义
    • 3.3. 万能引用与完美转发
    • 3.4. 移动构造与移动赋值
  • 4. default & delete
  • 5. 可变参数模板
  • 6. push_back 与 emplace_back
  • 7. lambda表达式
    • 7.1. 捕捉列表
  • 8. function包装器
    • 8.1. bind

C++11是继C++98之后,第二个真正意义上的标准。C++11增加的语法特性非常多,这里主要介绍实际比较实用的语法。
可以从C++官网对C++11版本特性进行全面的了解:https://en.cppreference.com/w/cpp/11

1. 列表初始化

C++11中的{}不仅可以用来初始化数组,已经扩展到可以用来初始化C++11的一切对象,而且使用时等号(=)可有可无。

void Test1()
{int a1 = { 1 };int a2{ 2 };vector<int> v1 = { 1,2,3,4,5 };vector<int> v2{ 1,2,3,4,5 };map<int, string> m1 = { {1, "one"}, {2, "two"} };map<int, string> m2{ {1, "one"}, {2, "two"} };// 也可以用在new表达式中int* p = new int[4]{ 0 };
}

注意一点:列表初始化,如果出现类型截断,是会报警告或者错误的。short c = 65535; short d { 65535 }; // err
STL中的很多容器能支持{}的初始化,其实是因为增加了std::initializer_list作为构造函数参数的设计,这样使容器的初始化更方便了。operator=同理。
在这里插入图片描述
std::initializer_list又是什么类型呢?

void Test2()
{auto il = { 1,2,3 };cout << typeid(il).name() << endl;
}

在这里插入图片描述
可以看到,{}对象其实就是std::initializer_list类型的对象。
这里建议,如果在使用容器时有大括号{}初始化的需求,可以选择使用;其它地方尽量不要使用,来保持语言风格的一致性。

2. auto & decltype

auto在C++98中是一个存储类型的说明符,但实质上没有什么价值。所以C++11中,auto就弃用了之前的用法,将其用于实现自动类型推导。auto此时仅仅只是占位符,编译阶段编译器根据初始化表达式推演出实际类型之后会替换auto

void Test3()
{int i = 10;auto p = i;auto pf = strcpy;cout << typeid(p).name() << endl;cout << typeid(pf).name() << endl;
}

在这里插入图片描述

decltype关键字可以将对象的类型声明为表达式生成的类型。

void Test4()
{char c = 'a';int i = 1;decltype(c * i) d1;decltype(strcpy) d2;cout << typeid(d1).name() << endl;cout << typeid(d2).name() << endl;
}

在这里插入图片描述

3. 右值引用

有右值引用,自然也有左值引用。其实C++11之前所学的引用都叫做左值引用。但无论左值引用还是右值引用,都是给对象取别名。
对于左值,我们可以取它的地址+对它赋值。但经过const修饰的左值可以取它的地址,却不能对它赋值。
对于右值,是不能取其地址的。
左值可以出现在赋值符号左边,右值可以出现在赋值符号右边,但反过来就不行。

void Test5()
{int i = 1;int* pi = &i;// 左值引用,给左值取别名int& ri = i; // 变量int*& rpi = pi; // 变量int& r = *pi; // 指针解引用double d = 2.2;// 右值引用,给右值取别名int&& rr1 = 10; // 字面常量double&& rr2 = i + d; // 表达式返回值
}

虽然右值不能被取地址,但右值引用后,会导致右值被存储到特定位置,从而可以取到该位置的地址。

void Test6()
{int&& rr1 = 10; // 右值引用cout << rr1 << endl;cout << &rr1 << endl; // 可以取地址rr1 = 20; // 可以赋值cout << rr1 << endl;cout << &rr1 << endl; // 可以取地址
}

在这里插入图片描述

3.1. 左右值引用比较

左值引用只能引用左值,不能引用右值;但const左值引用既可以引用左值,也可以引用右值。
右值引用只能引用右值,不能引用左值;但右值引用可以引用move以后的左值。

void Test7()
{int i = 10;int& r1 = i;//int& r2 = 10; // errconst int& r3 = i;const int& r4 = 10;//int&& r5 = i; // errint&& r6 = 10;int&& r7 = move(i);
}

3.2. 右值引用的意义

左值引用既可以引用左值,又可以通过const修饰引用右值,那为什么还要提出右值引用呢?
右值引用的加入其实是对左值引用一些缺陷上的补足。
比如说,stackpop接口返回值是voidvoid pop();)。但是如果要将返回值进行修改,使pop的同时返回其弹出的元素,那该如何设计其返回值类型呢?
如果设计成传值返回,当返回值需要深拷贝时,就会对效率造成影响。
如果设计成传引用返回,如果是左值引用,当出了函数作用域,返回的对象就不存在了,即引用也失效了。
此时,只能设计成右值引用返回。设计成右值引用,把将要被销毁的对象的资源转移出来,可以继续使用,而且不需要担心深拷贝的问题,填补了左值引用使用上的一些缺陷。
右值引用可以通过移动构造或移动赋值,对返回值是右值(将亡值)的资源进行转义,减少拷贝,延长资源生命周期。

3.3. 万能引用与完美转发

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<typename T>
void PerfectForward(T&& t)
{Fun(t);
}void Test8()
{int i = 1;PerfectForward(i);  // 左值PerfectForward(move(i)); // 右值const int ci = 2;PerfectForward(ci); // const 左值PerfectForward(move(ci)); // const 右值
}

在这里插入图片描述

// 如果想要在传递过程中保持最初的左值或右值属性,就需要用到完美转发
template<typename T>
void PerfectForward(T&& t)
{Fun(forward<T>(t));
}

在这里插入图片描述

3.4. 移动构造与移动赋值

C++11STL容器中都是增加了移动构造和移动赋值的。
在这里插入图片描述
移动构造和移动赋值是C++11新增的两个默认成员函数。
当没有自己实现移动构造函数,且没有实现析构、拷贝构造、拷贝赋值中的任何一个函数。那么编译器会自动生成一个默认的移动构造。其对于内置类型成员会执行按字节拷贝(值拷贝);对于自定义类型成员,会看这个成员是否实现了移动构造,如果实现了就调用,没有实现就调用拷贝构造。移动赋值同理。

4. default & delete

default和delete的使用可以让我们更好地控制默认函数的生成。
default可以强制某个默认函数的生成。比如:提供拷贝构造后,移动构造就不生成了,那么可以使用default显示指定移动构造生成。
如果不想要某个默认函数生成,只需要在函数声明处加上=delete即可。=delete修饰的函数也称为删除函数。

// 要求delete关键字实现一个类,只能在堆上创建对象
class HeapOnly
{
public:HeapOnly(){_str = new char[10];}~HeapOnly() = delete;void Destroy(){delete[] _str;operator delete(this);}
private:char* _str;
};
void Test9()
{HeapOnly* ptr = new HeapOnly;ptr->Destroy();
}

5. 可变参数模板

相比C++98固定的模板参数,C++11可变参数模板的的引入无疑是一个巨大的改进。

// 一个基本的函数可变参数模板定义
// Args是一个模板参数包,args是一个函数形参参数包,包含有大于等于0个参数
template<class ...Args>
void ShowList(Args... args)
{}

参数args前面有省略号,表示它是一个可变模板参数。把带有省略号的参数称为“参数包”,里面包含了N(N>=0)个模板参数。由于语法不支持使用args[i]这样的方式获取参数,需要使用一些特别的方法来一一获取参数包中的参数。

  1. 递归展开参数包
void ShowList() {} // 递归终止函数template <class T, class ...Args>
void ShowList(const T& val, Args... args)
{cout << "ShowList(" << val << ", " << sizeof...(args) <<"个参数)" << endl;ShowList(args...);
}void Test10()
{ShowList(1, 'A', string("one"));
}

在这里插入图片描述
2. 构建数组展开参数包

template<class T>
int PrintArg(const T& val)
{cout << val << " ";return 0;
}template <class ...Args>
void ShowList(Args... args)
{int a[] = { PrintArg(args)... };cout << sizeof(a) / sizeof(int) << endl;
}void Test11()
{ShowList(1, 'A', string("one"));
}

在这里插入图片描述
{ PrintArg(args)... }将会展开成 { PrintArg(arg1), PrintArg(arg2), PrintArg(arg3), ... },最终会创建一个元素值都为PrintArg返回值的数组。也就是说在构建数组的过程中参数包就展开了,而这个数组构建的目的纯粹就是为了在数组构建的过程中展开参数包。

6. push_back 与 emplace_back

在这里插入图片描述
在这里插入图片描述
push_back 与 emplace_back都是在end位置插入一个值。
可以注意到emplace接口支持可变模板参数,并且使用了万能引用。那么相对传统的插入接口,emplace接口优势到底在哪里呢?
在用法上,emplace支持可变参数,拿到参数后,会自己去创建对象,简化使用。

void Test12()
{vector<pair<int, int>> v;v.push_back(make_pair(1,1));v.push_back({ 2,2 });v.emplace_back(3, 3);
}

在底层上,emplace_back是直接构造,push_back是先构造,再拷贝构造/移动构造。
emplace_back直接构造确实会效率高一点,但实际上emplack_back和push_back的使用效果是差别不大的。

7. lambda表达式

lambda表达式实际是一个匿名函数。
lambda表达式语法:[capture-list](parameters)mutable->return-type{statement}

  • [capture-list]:捕捉列表。捕捉列表能够捕捉上下文中的变量供lambda使用,同时编译器也会根据[]来判断接下来的代码是否为lambda函数。
  • (parameters):参数列表。和普通函数的参数列表使用方式一致。如果不需要传参,()也可以省略。
  • mutable:默认情况下,lambda函数是一个const函数,而mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数列表为空)。
  • ->returntype:返回值类型声明。无返回值时可省略;返回值类型明确的情况下,也可省略,交由编译器自行推导返回值类型。
  • {statement}:函数体。在函数体内可以使用参数列表的参数和捕捉列表捕获的变量。
    从lambda表达式定义中,可以知道参数列表和返回值是可选部分,捕捉列表和函数体是可为空部分。所以最简单的lambda函数是[]{}

7.1. 捕捉列表

  • [var]:表示传值方式捕捉变量var
  • [=]:表示传值方式捕捉父作用域中的所有变量(包括this)
  • [&var]:表示传引用方式捕捉变量var
  • [&]:表示传引用方式捕捉父作用域中的所有变量(包括this)
  • [this]:表示传值方式捕捉this指针
void Test13()
{int x = 1;int y = 2;// 默认捕捉(传值捕捉)的变量不能修改// auto swap2 = [=]auto swap2 = [=]()mutable{int tmp = x;x = y;y = tmp;};swap2();cout << x << " " << y << endl;
}

即使对于传值捕捉的变量进行了修改,也不会对外部实际的变量造成修改。

所谓父作用域是指与lambda所在栈帧平行的栈帧空间。

static int si = 1;
void Test14()
{int i = 2;auto a = [=] {cout << si << endl; cout << i << endl; };a();
}

捕捉列表可由多个项组成,并以逗号分割。

void Test15()
{int a, b, c, d, e;a = b = c = d = e = 1;// 全部传值捕捉auto f1 = [=](){cout << a << b << c << d << e << endl;};f1();cout << a << endl;// 混合捕捉auto f2 = [=, &a](){++a;cout << a << b << c << d << e << endl;};f2();cout << a << endl;auto f3 = [&, a]()mutable{++a;cout << a << b << c << d << e << endl;};f3();cout << a << endl;
}

捕捉列表不允许变量重复传递。比如[=, this],this捕捉会重复,从而导致编译错误。
lambda表达式之间不能相互赋值。

void Test16()
{auto f1 = [] {cout << "hello world"; };auto f2 = [] {cout << "hello world"; };//f2 = f1; // errcout << typeid(f1).name() << endl;cout << typeid(f2).name() << endl;
}

在这里插入图片描述
lambda对象不能相互赋值,本质原因是因为类型不同,不能相互赋值。
这也说明,lambda在使用者角度是匿名的,在底层还是有名的。
实际在底层,编译器对于lambda表达式的处理,完全是按照函数对象的方式处理的。即:如果定义了一个lambda表达式,编译器会自动生成一个类(为其生成lambda_uuid的类型名),在该类中会重载operator()。
在这里插入图片描述

8. function包装器

C++中的function本质是一个类模板。
那为什么要有包装器呢?

template<class F, class T>
T useF(F f, T x)
{static int count = 0;cout << "count:" << ++count << endl;cout << "count:" << &count << endl;return f(x);
}
double f(double i)
{return i / 2;
}
struct Functor
{double operator()(double d){return d / 3;}
};void Test17()
{// 函数指针cout << useF(f, 11.11) << endl;// 函数对象cout << useF(Functor(), 11.11) << endl;// lambda表达式对象cout << useF([](double d)->double { return d / 4; }, 11.11) << endl;// 函数指针 | 仿函数/函数对象 | lambda(匿名函数) -> 都能像函数一样被使用
}

在这里插入图片描述
可以发现useF函数模板实例化了三份。但如果使用包装器就可以很好地优化上面的问题。
在这里插入图片描述
Ret:被调用函数的返回类型
Args…:被调用函数的形参

void Test18()
{// 函数指针function<double(double)> f1 = f;cout << useF(f1, 11.11) << endl;// 函数对象function<double(double)> f2 = Functor();cout << useF(f2, 11.11) << endl;// lambda表达式对象function<double(double)> f3 = [](double d)->double {return d / 4; };cout << useF(f3, 11.11) << endl;
}

在这里插入图片描述

8.1. bind

可以把bind看做是函数适配器。bind的作用主要是可以接收一个可调用对象(callable object),同时生成一个新的可调用对象来“适应”原对象的参数列表。使用bind我们可以把一个原本接收 n 个参数的函数 f,通过绑定一些参数,然后返回一个接收 m 个参数的新函数,同时可以做到对参数顺序的调整。
在这里插入图片描述
bind的一般使用形式:auto newCallable = bind(callable, arg_list)
newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应callable的参数。当调用newCallable时,newCallable会调用callable,并传递给它arg_list中的参数。
arg_list中的参数可能包含形如 _n (n 是一个整数)的名字,这些参数是“占位符”,表示newCallable的参数。这些“占位符”占据了传递给newCallable的参数的“位置”。例如,_1为newCallable的第一个参数,_2为第二个参数,…

class Plus
{
public:static int plusi(int a, int b){return a + b;}double plusd(double a, double b){return a + b;}
};void Test19()
{function<int(int, int)> f1 = Plus::plusi;function<double(Plus, double, double)> f2 = &Plus::plusd;cout << f1(1, 2) << endl;cout << f2(Plus(), 1.1, 2.2) << endl;// 调整参数个数,绑死固定参数function<int(int, int)> f3 = bind(Plus::plusi, placeholders::_1, placeholders::_2);function<double(double, double)> f4 = bind(&Plus::plusd, Plus(), placeholders::_1, placeholders::_2);cout << f3(1, 2) << endl;cout << f4(1.1, 2.2) << endl;
}

在这里插入图片描述


文章转载自:
http://brat.hfytgp.cn
http://barong.hfytgp.cn
http://apotropaion.hfytgp.cn
http://ably.hfytgp.cn
http://cardiometer.hfytgp.cn
http://affranchise.hfytgp.cn
http://amerika.hfytgp.cn
http://arete.hfytgp.cn
http://applausive.hfytgp.cn
http://bunyan.hfytgp.cn
http://chandigarh.hfytgp.cn
http://bretagne.hfytgp.cn
http://bellyhold.hfytgp.cn
http://bluebill.hfytgp.cn
http://ameliorable.hfytgp.cn
http://antihero.hfytgp.cn
http://basecourt.hfytgp.cn
http://brawniness.hfytgp.cn
http://aspirate.hfytgp.cn
http://capotasto.hfytgp.cn
http://buff.hfytgp.cn
http://cabobs.hfytgp.cn
http://carcinogenesis.hfytgp.cn
http://chromograph.hfytgp.cn
http://advisee.hfytgp.cn
http://catercornered.hfytgp.cn
http://brigatisti.hfytgp.cn
http://anthracitous.hfytgp.cn
http://cheapness.hfytgp.cn
http://archespore.hfytgp.cn
http://acrobatism.hfytgp.cn
http://carnival.hfytgp.cn
http://address.hfytgp.cn
http://chang.hfytgp.cn
http://additory.hfytgp.cn
http://avowably.hfytgp.cn
http://ballista.hfytgp.cn
http://christology.hfytgp.cn
http://backstab.hfytgp.cn
http://algeria.hfytgp.cn
http://alfred.hfytgp.cn
http://avertible.hfytgp.cn
http://camenae.hfytgp.cn
http://argentite.hfytgp.cn
http://biosociology.hfytgp.cn
http://allusion.hfytgp.cn
http://cabalism.hfytgp.cn
http://acicula.hfytgp.cn
http://attorn.hfytgp.cn
http://bilge.hfytgp.cn
http://choreal.hfytgp.cn
http://cameronian.hfytgp.cn
http://angler.hfytgp.cn
http://aphasiac.hfytgp.cn
http://broadax.hfytgp.cn
http://chronometrical.hfytgp.cn
http://arrowwood.hfytgp.cn
http://chrysarobin.hfytgp.cn
http://achromic.hfytgp.cn
http://aryballos.hfytgp.cn
http://bronzy.hfytgp.cn
http://briseis.hfytgp.cn
http://acini.hfytgp.cn
http://avow.hfytgp.cn
http://bioglass.hfytgp.cn
http://anthracosis.hfytgp.cn
http://baa.hfytgp.cn
http://bobolink.hfytgp.cn
http://chinny.hfytgp.cn
http://antimony.hfytgp.cn
http://amphithecium.hfytgp.cn
http://adorn.hfytgp.cn
http://anglophone.hfytgp.cn
http://basting.hfytgp.cn
http://bosket.hfytgp.cn
http://amplification.hfytgp.cn
http://annularity.hfytgp.cn
http://acrospire.hfytgp.cn
http://cheth.hfytgp.cn
http://canting.hfytgp.cn
http://ancilla.hfytgp.cn
http://bacciform.hfytgp.cn
http://architecturally.hfytgp.cn
http://awry.hfytgp.cn
http://acetaldehydase.hfytgp.cn
http://apprehensively.hfytgp.cn
http://actuator.hfytgp.cn
http://arty.hfytgp.cn
http://acotyledonous.hfytgp.cn
http://bikeway.hfytgp.cn
http://acupuncturist.hfytgp.cn
http://aground.hfytgp.cn
http://beatles.hfytgp.cn
http://biogeocoenology.hfytgp.cn
http://aquiprata.hfytgp.cn
http://bazzoka.hfytgp.cn
http://bunchberry.hfytgp.cn
http://cephaloid.hfytgp.cn
http://cannibalize.hfytgp.cn
http://bowshock.hfytgp.cn
http://www.tj-hxxt.cn/news/37784.html

相关文章:

  • 北京市网站建设公司一份完整的营销策划方案
  • 微信小程序开发定制公司在线seo优化
  • 北流做网站武汉网站设计十年乐云seo
  • 武汉软件公司都有哪些seo网站内容优化有哪些
  • 科技网站制作案例中国万网域名查询
  • 七色板网站建设徐州seo外包
  • 桂林北站附近的景点seo分析师招聘
  • 网站建设与管理培训总结电商运营平台
  • 个人网站怎么注册最吸引人的营销广告词
  • 资源网站模板下载百度广告一级代理
  • 精品网络小说推荐百度上海推广优化公司
  • 自己做的网站怎么样合法seo网课培训
  • 如何做直播做菜视频网站山西太原百度公司
  • 采招网是怎样做的网站重庆百度seo排名
  • 做母婴网站设计思路网站设计用什么软件
  • 有了源码怎么做网站百度一下你就知道手机版官网
  • 七星彩的网站怎么做的广州网络广告推广公司
  • 政府网站建设要求 国务院贵阳网络推广外包
  • 教做布艺的网站精准客户资源购买
  • 有没有做粤菜的网站市场监督管理局上班时间
  • 广州哪里有做网站公司营销策划方案
  • 建设政府网站的成本软文推广什么意思
  • 成都网站建设外贸北京百度科技有限公司电话
  • 用来做视频连接的网站seo网站优化培训
  • 网站建设营销词驾校推广网络营销方案
  • 做网站原则全国最好的广告公司加盟
  • 承德建设工程信息网站山西搜索引擎优化
  • 网站建设活动方案我们公司在做网站推广
  • 登录门户网站2022年每日新闻摘抄10一30字
  • 重庆 网站备案上海排名seo公司