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

诚信网站体系建设工作总结网站加v怎么做

诚信网站体系建设工作总结,网站加v怎么做,中移建设有限公司官方网站,合肥外贸网站推广目录 一、列表初始化 1.1 {}初始化 1.2 initializer_list 二、变量类型推导 2.1 auto 2.2 decltype 三、STL中一些变化 3.1 新增容器 四、lambda表达式 4.1 C98中的一个例子 4.2 lambda表达式 4.3 函数对象与lambda表达式 五、包装器 5.1 function包装器 5.2 fu…

目录

一、列表初始化

1.1 {}初始化

1.2 initializer_list

二、变量类型推导

2.1 auto

2.2 decltype

三、STL中一些变化

3.1 新增容器

四、lambda表达式

4.1 C++98中的一个例子

4.2 lambda表达式

4.3 函数对象与lambda表达式

五、包装器

5.1 function包装器

5.2 function 的使用方法

5.3 bind


一、列表初始化

1.1 {}初始化

C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自
定义的类型,使用初始化列表时,可添加等号(=),也可不添加

    int a[2]{ 1,2 };
    int b{ 3 };
    vector<int> c{ 4,5,6,7,8 };

1.2 initializer_list

我们能使用{}初始化,是因为initializer_list的原因,下面我们来了解一下它。

它是一个新的C++的容器,一个类模板,是一个用于初始化的工具。

举一个例子,你如何用下面的数组来初始化vector呢?

int arr[5] = { 1, 2, 3, 4 };

vector<int> v;

你可能会用下面的代码来初始化

for (int i = 0; i < 5; i++)
{
    v.push_back(arr[i]);
}

但是这好像太麻烦了吧。C++11后,STL的容器都增加了新的构造函数,可以通过initializer_list来初始化容器。

vector<int> v({ 1, 2, 3, 4, 5 });

这个写法,是单参数的类型转化,因为{ 1, 2, 3, 4, 5 }整体就是一个initializer_list类型的参数

同样的,我们也可以用它来初始化map

map<string, string> m = { {"apple","苹果"}, {"banana","香蕉"}, {"pear", "梨"} };

最外层的{ }就是一个initializer_list。

它的接口也很简单

(constructor)构造空 initializer_list
size返回列表大小
begin返回迭代器的开头
end返回迭代器的最后

我们也可以看出来initializer_list的本质上是一个通过迭代器访问数组的容器。当其它容器通过initializer_list构造自己时,其实就是通过迭代器遍历那个存储了节点的数组,然后把数组元素一个一个插入。

换而言之,下面这两种写法是一样的。

initializer_list<int> lt = { 1, 2, 3, 4 };

list<int> l1({ 1, 2, 3, 4 });
list<int> l2(lt.begin(), lt.end());


二、变量类型推导

2.1 auto

在C++98中auto是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局
部的变量默认就是自动存储类型,所以auto就没什么价值了。C++11中废弃auto原来的用法,将
其用于实现自动类型推断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初
始化值的类型。

auto i = 1;//整型
auto d = 3.14;//浮点型
auto p = &i;//指针
vector<int> v;
auto it = v.begin();//迭代器

2.2 decltype

decltype可以检测一个变量的类型,并且拿这个类型去声明新的类型。比如下面这个

int i = 0;
decltype(i) x = 5;

decltype(i)检测出i的类型为int,于是decltype(i)整体就变成int,从而定义出一个新的变量x。


三、STL中一些变化

3.1 新增容器

用橘色圈起来是C++11中的一些几个新容器。但最有用的是unordered_map、unordered_set。


四、lambda表达式

4.1 C++98中的一个例子

函数对象,又称为仿函数,即可以想函数一样使用的对象,就是在类中重载了operator()运算符的
类对象。

在C++98中,如果想要对一个结构体进行排序,就需要用户自己写仿函数。

struct Goods
{string _name;  // 名字double _price; // 价格int _evaluate; // 评价Goods(const char* str, double price, int evaluate):_name(str), _price(price), _evaluate(evaluate){}
};

如果我们想要按照价格排序

struct ComparePriceLess
{bool operator()(const Goods& gl, const Goods& gr){return gl._price < gr._price;}
};struct ComparePriceGreater
{bool operator()(const Goods& gl, const Goods& gr){return gl._price > gr._price;}
};

随着C++语法的发展,人们开始觉得上面的写法太复杂了,每次为了实现一个algorithm算法, 
都要重新去写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名,
这些都给编程者带来了极大的不便。因此,在C++11语法中出现了Lambda表达式。

4.2 lambda表达式

lambda表达式书写格式:

[capture_list] (parameters) mutable -> return_type {statement}

我们来看看各部分是做什么的

  • [capture_list]:捕捉列表。编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用
  • (parameters):参数列表。普通函数的参数列表一致。如果不需要参数传递,则可以
    连同()一起省略
  • mutable:一个关键字。mutable可以取消其常量性。使用该修饰符时,参数列表不可省略
  • -> return_type:返回值类型。用追踪返回类型形式声明函数的返回值类型,返回值类型明确情况下,可省略,由编译器对返回类型进行推导。没有返回值时此部分也可省略
  • {statement}: 函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获
    到的变量

举一个例子,下面是一个完整的lambda表达式。

auto add = [](int a, int b)mutable -> int { return a + b; };

当然我们也可以将其省略成下面这个式子

auto add = [](int a, int b) { return a + b; };

那lambda表达式有什么作用呢?答案是:lambda会返回一个仿函数对象

比如我们上面写的例子,其实add就是一个仿函数对象了,我们可以直接按照调用函数的方式来调用这个仿函数:add(1, 2);。但是要注意, lambda表达式实际上可以理解为无名函数,该函数无法直接调用,如果想要直接调用,因此必须使用auto来接受这个仿函数对象。


下面我们再来详细地讲一讲lambda表达式最前面的[]的作用。

[]描述了上下文中那些数据可以被lambda使用,以及使用的方式是传值还是传引用。

  • [var]:表示值传递方式捕捉变量var
  • [=]:表示值传递方式捕获所有父作用域中的变量(包括this)
  • [&var]:表示引用传递捕捉变量var
  • [&]:表示引用传递捕捉所有父作用域中的变量(包括this)
  • [this]:表示值传递方式捕捉当前的this指针

举几个例子解释一下。

int x = 1;
int y = 2;

/*如果直接通过变量名捕获,此时是传值调用,修改函数体内部的变量,不会影响父作用域的变量*/

auto add = [x, y] {return x + y; };
 

/*通过直接传值捕获的变量,自带const属性,不允许修改。此时代码就会报错*/

/*auto add = [x, y] 
    {
        x += 5;
        y += 5;
    };*/

/*mutable可以让被捕获的参数可以修改。需要注意的是如果使用了mutable,()不可省略*/

auto add = [x, y] () mutable
    {
        x += 5;
        y += 5;
    };


/*以传引用的方式来捕获变量,此时修改函数内部的x和y,就是在修改父作用域的x和y。如果使用了传引用捕获变量,就算没有mutable也可以修改参数*/

auto add = [&x, &y]
    {
        x += 5;
        y += 5;
    };
 

/*[=]是以传值的形式捕获父作用域所有变量,[&]是以传引用的形式捕获父作用域所有变量*/

auto add = [=]
    {
        return x + y;
    };

auto add = [&]
    {
        return x + y;
    };

/*

我们还可以把传值和传引用混合使用,让部分参数传参,部分参数传引用。

[x, &y]:以传值的形式捕获x,以传引用的形式捕获y
[=, &x]:以传值的形式捕获父作用域所有变量,以传引用的形式捕获x
[&, x]:以传值的形式捕获x,以传引用的形式捕获父作用域所有变量

*/

有了lambda表达式之后,我们就可以改变一下最开始的排序了

vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2, 3 }, { "菠萝", 1.5, 4 } };sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._price < g2._price; });sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._price > g2._price; });

4.3 函数对象与lambda表达式

从使用方式上来看,函数对象与lambda表达式完全一样。

函数对象将rate作为其成员变量,在定义对象时给出初始值即可,lambda表达式通过捕获列表可
以直接将该变量捕获到。

实际在底层编译器对于lambda表达式的处理方式,完全就是按照函数对象的方式处理的,即:如
果定义了一个lambda表达式,编译器会自动生成一个类,在该类中重载了operator()。


五、包装器

当我们在寄快递的时候,快递会被包装,这样我们就可以统一的在上面贴上快递信息,随后以统一的形式管理所有快递。包装器也是如此,包装器可以将具有相似属性的东西包装起来成为一个整体。

5.1 function包装器

function包装器,也叫作适配器。C++中的function本质是一个类模板,也是一个包装器。

那么我们在什么时候会用到包装器呢?我们一步步来看

我们首先回忆一下我们知道的可调用对象

  1. 函数指针
  2. 仿函数实例化出的对象
  3. lambda表达式

但是它们都有各自的缺点

函数指针:类型复杂,不好用
仿函数实例化出的对象:哪怕参数返回值都相同,仿函数之间的类型也不同
lambda表达式:类型是随机的,必须用auto接收

可以看到,这三者都有类型方面的大问题,我们也没有一种方式可以把所有参数类型和返回值类型相同的函数,统一的管理起来,让它们都变成一个类型?这个时候就用到包装器了。

std::function在头文件<functional>


// 类模板原型如下
template <class T> function;     // undefined
template <class Ret, class... Args>
class function<Ret(Args...)>;


模板参数说明:
Ret: 被调用函数的返回类型
Args…:被调用函数的形参

function包装器,只要是返回值和参数列表都相同的可调用对象,经过这一层封装,都会变成相同的类型。

举一个例子

double func(double x)
{
    return x / 2;
}

struct Functor
{
    double operator()(double x)
    {
        return x / 3;
    }
};

int main()
{
    auto lambadaFunc = [](double d) {return d / 4; };

     /*func,Functor,lambadaFunc 。它们的返回值都是double,参数类型也是double,因此可以经过包装器包装为function<double<double>>*/

     /*现在三者的类型就都是function<double(double)>*/

    function<double(double)> func1 = func;
    function<double(double)> func2 = Functor();
    function<double(double)> func3 = lambadaFunc;

    return 0;
}

5.2 function 的使用方法

// 使用方法如下:
#include <functional>
int f(int a, int b)
{
        return a + b;
}
struct Functor
{
public:
         int operator() (int a, int b)
         {
                 return a + b;
         }
};

class Plus
{
public:
         static int plusi(int a, int b)
         {
                return a + b;
         }
         double plusd(double a, double b)
         {
                 return a + b;
         }

};
int main()
{
         // 函数名(函数指针)
         std::function<int(int, int)> func1 = f;
         cout << func1(1, 2) << endl;
         // 函数对象
         std::function<int(int, int)> func2 = Functor();
         cout << func2(1, 2) << endl;
         // lamber表达式
         std::function<int(int, int)> func3 = [](const int a, const int b) 
        {return a + b; };
         cout << func3(1, 2) << endl;
 
         // 类的成员函数
         std::function<int(int, int)> func4 = &Plus::plusi;
         cout << func4(1, 2) << endl;
         std::function<double(Plus, double, double)> func5 = &Plus::plusd;
         cout << func5(Plus(), 1.1, 2.2) << endl;


         return 0;
}

5.3 bind

bind函数

  1. 是一个函数模板
  2. 其接收多个参数,第一个参数为可调用对象,后续参数为该可调用对象的参数
  3. 其主要有两个功能:改变参数顺序,给指定参数绑定固定值

C++11后新增一个命名空间域placeholders,其内部会存储很多变量,这些变量用于函数的传参,变量的名字为_x表示第x个参数。

举个例子

int sub(int a, int b)
{
    return a - b;
}

int main()
{

        /*sub这个参数是一个可调用对象。
        placeholders::_2表示第二个参数,

        placeholders::_1表示第一个参数*/
        auto f1 = bind(sub, placeholders::_2, placeholders::_1);

        /*f1最后拿到了这个bind封装的函数,那么f1(3, 5)执行的并不是3 - 5,而是5 - 3*/

        f1(3, 5);

        return 0;
}

int sub(int a, int b)
{
    return a - b;
}

int main()
{

        /*第一个参数为可调用对象sub,第二个参数是一个固定值3.14,参数a都固定为3.14*/
        auto f2 = bind(sub, 3.14, placeholders::_1);

        f2(10);//3.14 - 10

        return 0;
}

bind 函数还可以用来处理函数的返回值

int add(int x, int y) {
    return x + y;
}

int main() {
       // 绑定 add 函数,并将返回值乘以 2
        auto doubleAdd = bind([](int result) { return result * 2; },         add(placeholders::_1,placeholders::_2));
        int result = doubleAdd(3, 4);
        cout << result << endl; // 输出 14


        return 0;
}


文章转载自:

http://EDGnu6QN.nfpct.cn
http://lcbMPHda.nfpct.cn
http://8wMUs7OM.nfpct.cn
http://4xUJ2GX7.nfpct.cn
http://oCENmfin.nfpct.cn
http://DPIzMip1.nfpct.cn
http://EmWgkdSZ.nfpct.cn
http://xP7gEtuF.nfpct.cn
http://ymg5GVRj.nfpct.cn
http://znPkQ3HU.nfpct.cn
http://36yqPe9b.nfpct.cn
http://nLhHRMt5.nfpct.cn
http://G2lpO2XV.nfpct.cn
http://wytcYgbq.nfpct.cn
http://chOPmyFv.nfpct.cn
http://9YDXKdnj.nfpct.cn
http://iiawi6B8.nfpct.cn
http://SdDEG149.nfpct.cn
http://T95BaxJC.nfpct.cn
http://xECNQyXr.nfpct.cn
http://4J3DCF6e.nfpct.cn
http://HU3Rr0Oe.nfpct.cn
http://cqRphdbs.nfpct.cn
http://QYwyZURD.nfpct.cn
http://Hnjgbe6o.nfpct.cn
http://tcshcFoI.nfpct.cn
http://90Hdw8dw.nfpct.cn
http://BKDOOBlB.nfpct.cn
http://J7JG13ev.nfpct.cn
http://GxG0kw78.nfpct.cn
http://www.dtcms.com/wzjs/701529.html

相关文章:

  • 哈尔滨公司网站建设多少钱广告设计公司实习周记
  • 大型商城网站建设方案一站式婚庆公司
  • 档案网站的建设方案域名注册成功后怎么使用网站
  • 企业网站空间在哪里深圳家具设计公司排名
  • 如何检测做的网站的兼容性长春火车站停车场24小时收费标准
  • 网站设计服务费英文成功的电商网站
  • 怎么把自己做的网站放上网络那个网站做图片好看
  • 如何免费弄一个网站wordpress的数据库
  • 做网站软件 手机会展门户网站源码
  • 沈阳建网站 哪家好官方网站模板
  • 怎么做网站编辑上海服装外贸公司排名
  • 通州宋庄网站建设网站开发保存学习进度的方案
  • 单位建设网站申请信用卡小说网站怎么做词
  • 襄阳做网站公司题库小程序源码
  • 网站后台开发招聘网站对比这么做
  • 深圳网站建设全包muse做网站
  • 西安培训机构图片网站的优化
  • 网站建设合同 果动.l哈尔滨教育学会网站建设
  • 做义工旅行有哪些网站华为网站建设策划书
  • 新加坡域名注册网站哈尔滨建站模板厂家
  • 阿坝州城乡建设网站wordpress 调用分类文章
  • 天河建设网站开发天津市建设执业资格注册中心网站
  • 北京网站建设公司 蓝纤科技微博推广效果怎么样
  • flashfxp链接网站作文网投稿网站
  • 帮朋友做网站的坑厦门模板做网站
  • 做国外电影网站互联网创业项目
  • 煤炭网站建设规划书公司网站找哪家
  • 网站都有哪些类型做什么软件做网站效率最好
  • 做网站需要什么资料网站建设分为哪几种类型
  • 沈阳高端网站制作公司哪家好陕西省网页制作