C++11 auto、declty和peLambda表达式特性

C++11新特性

一 智能指针和智能指针自实现
智能指针是C++11中新特性,c++11 —> c++ 2011
C++14 — C++ 2014 c++17 — C++ 2017
智能指针
在C++库中也是类模板之一
实际上将指针封装在一个类,通过对象来管理指针
作用主要用来管理内存,在c++中,是一种管理资源,避免泄露内存的习惯用法,也称RAII(资源获取及初始化)
在使用系统提供的智能指针

class A
{

public:
    A()
    {
        cout << " A() " << endl;
    }
    ~A()
    {
        cout << "~A()" << endl;
    }

    //定义一个测试函数
    void func()
    {
        cout << "A::func()"<<endl;
    }
};

//智能指针自实现
template<class T>
class myautoptr
{
public:
    explicit myautoptr(T* pa)
    {
        this->m_pa = pa;
    }

    ~myautoptr()
    {
        delete m_pa;
    }

    //重新实现-> 和 *运算重载
    //->
#if 1
    T* operator ->()
    {
        return m_pa;
    }
#endif
    //*
    T& operator *()
    {
        return *m_pa;
    }

private:
    T* m_pa;
};
int main()
{
#if 0
    auto_ptr<A> pa(new A); //构造函数(A*p)
    pa->func();

    A* aa = new A; //在堆上,创建对象时,那么,程序也很可能忘记释放,那么就造成内存泄露
    aa->func();
    delete aa;

    //auto_ptr 在这个类板中的析构函数怀疑它对某个类型的指针进行了自动释放
    /*

 A()
A::func()
~A()  ----->自动去释放了程序员手动创建的堆对象
    */
#endif
   myautoptr<A> paa(new A); //实现自定义智能指针
   paa->func();
   (*paa).func();
    return 0;
}

二 C++ 11 auto 和 decltype关键字
1 auto
auto 关键字定义变量,但这个变量的类型,由编译器自动判断变量的类型
class A
{

public:
    A()
    {
        cout << " A() " << endl;
    }
    ~A()
    {
        cout << "~A()" << endl;
    }

    //定义一个测试函数
    void func()
    {
        cout << "A::func()"<<endl;
    }
};

int main()
{

    auto i = 10; // i 是 int
    auto p = new A; // p is A*
    //如果类型比较短,使用auto并不见得好,如果类型名字很长,比如类模板
    map<int, string> Map;
      auto it = Map.begin(); //使用auto可以节省快速 ---map<int, string>::iterator
      
    return 0;
}

二 C++ 11 auto 和 decltype关键字
1 auto
auto 关键字定义变量,但这个变量的类型,由编译器自动判断变量的类型

class A
{

public:
    A()
    {
        cout << " A() " << endl;
    }
    ~A()
    {
        cout << "~A()" << endl;
    }

    //定义一个测试函数
    void func()
    {
        cout << "A::func()"<<endl;
    }
};

int main()
{

    auto i = 10; // i 是 int
    auto p = new A; // p is A*
    //如果类型比较短,使用auto并不见得好,如果类型名字很长,比如类模板
    map<int, string> Map;
      auto it = Map.begin(); //使用auto可以节省快速 ---map<int, string>::iterator
      
    return 0;
}

2 decltype
decltype关键字可以用于表达式的类型
有时我们只想从表达式的类型推断出要定义的变量类型,但是不想用其值进行初始化的时候,
C++11新标准引入了decltype类型说明符,它的作用是选择并返回操作数的数据类型,在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值。

class A{
public:
    double x;
};

//在C++11 中,函数返回的值若为auto,则需要跟decltype
//在C++14 中, 则可以不用decltype
template<class T1,class T2>
auto add(T1 x,T2 y)->decltype (x+y)
{
    return x+y;
}

/*
decltype总结:
   1. auto 忽略const,decltype保留顶层const
   2.对引用操作,auto推出原有类型,decltype推断出为引用
   3.对解引用操作,,auto推出原有类型,decltype推断出为引用
   4.auto推断会实际执行,,decltype不会执行,只会分析

*/
int main()
{
#if 1
    //[1] 跟基本数据类型
    int i;
    double d;
    const int  x = 10;
    decltype (x) y = 10; //对于decltype保留顶层const
    A* a = new A();
    decltype (a) x1; // x1 is A*
    decltype (a->x) x3; //x3 is double
    x3 = 10;
    x1->x = 10;

    //[2] 跟指针结合
    int tempA = 2;
    int* ptrTempA = &tempA;

    decltype (ptrTempA) decTempA; //常规使用decTempA为一个int*的指针

    // declaration of reference variable 'decTempB' requires an initializer
    // 表达内容为解引用,decTempB声明表示为一个引用,必须初始化,否则,编译不通过
    //decltype (*ptrTempA) decTempB = tempA;

    auto decTempc = ptrTempA;
   cout << *decTempc << endl;

#endif
 //[3] auto 与 decltype的使用  函数的返回值类型auto,则需要decltype来配合使用
    auto ret = add(5,5.0);
    cout << "ret = " << ret << endl;
    return 0;
}

三 Lambda表达式定义
在函数调用的地方,来实现对函数的定义
它的结构为:
一个[]就表示Lambda开始:

  1. [capture]:捕获列表。捕捉列表总是出现在Lambda函数的开始处。[]是Lambda引出符,
    编译器根据该引出符判断,接下来是否是Lambda函数,
    捕获列表由0个或者多个捕捉项组成,如果是有多个,中间用逗号隔开,捕捉列表形式:
  1. [var] 表示值传递,捕捉变量的val的值
    2)[=] 表示值传递
    3)[&] 或者 [&val] 表示地址传递或者引用传递
    4)[=,&a,&b] 表示以引用来捕捉变量 a和b,其他变量使用值传递
    5)[&,a,this] 表示以值来捕捉变量 a和this,其他变量使用引用传递
int a = 10,b = 20;
int ret = [=]()->int{return a+b};

2.(parameters):参数列表,可选项,与普通函数的参数列表一致。如果不需要参数传递,可以
连同括号一起省略
3.mutable:mutable修饰符 ---- 可变的,易变的,跟const相对,默认情况下,Lambda
函数总是一个const函数,mutable可以取消常量性,可以在Lambda函数修改参数的值
4.->return-type:返回值 类型,可选项,用追踪返回类型形式声明 函数的返回类型,如果
不需要返回值的时候,那么,也可以把符号"->"一起省略
5.{body/statement}:函数体,内容和写法与普通函数一样
6.specifiers exception attr:异常属性,可选
普通函数组成部分:函数名 参数列表 传参形式 返回值 函数体 const属性 异常属性
Lambda函数组成部分:
(parameters) ------> 参数列表
[=,&] ------> 传参形式
->return-type —> 返回类型
{body/statement} — 函数体
mutable修饰符 —> 取消const属性
基本使用:

//普通函数
int add(int a,int b)
{
    return a+b;
}
//假如一个系统中,代码量比较大,


int main()
{
   int a =10,b=20;

  // cout << add(a,b);
   auto ret = [=]()->int{ //默认情况下是一个const 函数
      // a++; //不能修改其参数值
       return  a+b;
   };

   //为了避免函数的定义和调用的层次清晰,可以使用lambda来在函数调用的地方,来实现功能
   auto ret2 = [a,&b]()mutable ->int{
        a++; //mutable修饰符允许函数来修改参数值,它将函数的const属性去掉 a = 11,该变量就相当于该lambda函数中局部变量

        b = 50; //&以引用的方式传递,可以直接修改外部变量值
       return  a+b;
   };
   int retsult = ret2();
   cout << retsult << endl; //61
   cout << "a = " << a << endl; //10
   cout << "b = " << b << endl; //50
    return 0;
}

lambda表达式在STL算法库应用
int main()
{
   // STL --- for_each算法
    /*
    template <class InputIterator, class Function>
   Function for_each (InputIterator first, InputIterator last, Function fn);
   InputIterator first ---- 数据的首地址,迭代器头指针,或者 容器的首地址(数组地址)
   InputIterator last ----- 容器的末尾地址(最后元素的下一个)迭代器尾指针
   */
    int a[5] = {10,2,3,4,5};

    int total = 0;

    for_each(a,a+5,[&](int& x){
        total += x;
        x++; //指向数组的下一个元素,将该元素的值获取给x
    });
    cout << total;

    for_each(a,a+5,[=](int a)
    {
        cout << a << " ";
    });
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值