• C++11_新语法


    版权声明:本文为博主原创文章,未经博主允许不得转载。

    本节主要介绍C++的新特性,对于C++的基础语法不再讲解.由于编译器的不同.在某些地方可能有些差异,但是无太大影响.

    讲解本节知识之前先确认你的C++支持度[__cplusplus]

    #include <iostream>
    int main(int argc, const char * argv[]) {
        std::cout<<__cplusplus<<std::endl;
        return 0;
    }  

     会看到这样,说明支持C++11


    主要介绍如下: 

    新特性 1  模板套模板

     新特性 2  空指针

     新特性 3  新auto

     新特性 4  新初始化

     新特性 5  initializer_list<>

     新特性 6   新for循环

     新特性 7  =default与=delete

     新特性 8  Alias Template(template typedef)

     新特性 9  Type Alias

     新特性 10  noexcept,override,final关键字

     新特性 11  decltype


    新特性 1  模板套模板

    在旧版本的C++中模板套用模板可能要加空格,像这样

    vector<list<int> > //旧板中需要加空格
    vector<list<int>>  //新模板中不需要加

    新特性 2  空指针

    新规定中nullptr可以代替0和NULL(0指针)

    void f(int)   { cout << "f(int) be called" << endl; }
    void f(void*) { cout << "f(void*) be called" << endl; }
    
    f(0);       //calls f(int)
    f(NULL);    //calls f(int) if NULL is 0
    f(nullptr); //calls f(void*) 

    新特性 3  新auto

    1.自动识别类型(编译器的实参推倒)

    auto i = 42; //自动识别 i为 int
    auto d = func(); //自动识别d为函数返回值

    2.如果初始化表达式是引用,则去除引用语义.如果auto关键字带上&号,则不去除const语意

    int a = 10;
    int &b = a;
    
    auto c = b;//c的类型为int而非int&(去除引用)
    auto &d = b;//此时c的类型才为int&

    3.如果初始化表达式为const或volatile,则除去const/volatile语义.

    const int ci=i,&cr=i;
    auto a=ci;      //a为int(忽略顶层const)
    auto b=cr;      //b为int(忽略顶层const,cr是引用)
    auto c=&i;      //c为int *
    auto d=&ci;     //d是pointer to const int(&ci为底层const

    4.初始化表达式为数组时,auto关键字推导类型为指针.

    int main()
    {
        int array[3]{ 1, 2, 3 };
        auto array_b = array;
        std::cout << typeid(array_b).name() << std::endl;
        
        return 0;
    }

     输出结果Pi(int*)

    注意事项

    1.auto声明的变量必须要初始化,否则编译器不能判断变量的类型.

    2.auto不能被声明为返回值(但可以与decltype结合使用做返回值的站位下文有),auto不能作为形参,auto不能被修饰为模板参数


    新特性 4  新初始化

    C++11之前的初始化

    Rect r1 = {3,7,20,25};//大括号
    Rect r2(3,7,20,25) ;//小括号
    int arry[3] = {1,2,3};//[]

    C++11之后一切的初始化都可以用 {} 代替

    int value[] {1,2,3};
    vector<int> v {1,2,3};
    complex<double> c {1,2,3};

    新初始化的优点

    int i; //初始值不知道
    int i{}; //初始值是0
    int * p;//初始值不知道
    int * p{}; //初始值是nullptr
    
    //{}  不允许窄化转换
    int x1(5.3);它会被初始化为5
    int x2{5.3};它会报错

     新特性 5  initializer_list<>

    一包东西,但是类型得是相同的,实现C++源码的重要语法,知道怎么用就可以.传递过程不需要我们担心,编译器会自动处理

    int main(int argc, const char * argv[]) {
        std::initializer_list<int> t1 {1,2,3,4};
        std::cout<<max(t1)<<std::endl;//新的max() 传参采用 initializer_list 不在受限于参数个数
        return 0;
    }

      输出结果


     新特性 6   新for循环

    新的for循环采用for(del声明 : coll容器),与旧for()不冲突

    #include <iostream>
    #include <vector>
    
    int main()
    {
        std::vector<int> v1 {1,2,3,4,5};
        for (auto i: v1) { //此时的auto变量i是 pass by value 不能改变容器中的成员如果想改变其成员,需要pass by reference
            std::cout<< i <<std::endl;
        }
        return 0;
    }

    输出结果

    pass by reference写法

    int main()
    {
        std::vector<int> v1 {1,2,3,4,5};
        for (auto& i: v1) { 
            i *= 3;//此时传递的是引用,可以改变vector中的成员
        }
        return 0;
    }

    新特性 7  =default与=delete

    class Zoo//delete删掉编译器给的 default要编译器给的即使定义了也要让编译器给出
    {
    public:
        Zoo(int i1,int i2) : d1(i1),d2(i2) {}
        Zoo(const Zoo&) = delete;//拷贝构造函数
        Zoo(Zoo&&) = default;//右值引用 Move()
        Zoo & operator = (const Zoo&) = default;
        Zoo operator = (const Zoo&&) = delete;
        virtual ~Zoo();
        
    private:
        int d1,d2;
    };

    a.  =default用于普通函数无意义(构造函数可以共存)

    b.  =delete用于普通函数可以取代于virtual function = 0

    c.  BIG-Three 默认构造函数 默认拷贝构造函数 默认析够函数 他们三个函数的作用是给编译器防止一个幕后藏身的地方 如父类的构造函数调用过程.

        类中有指针成员,需要重写BIG-Three没有则不用

    d.  类中讲拷贝构造与构造函数声明成private 如果你的类继承自noncopyable 那么你的类也不能被拷贝

    简单实现一下noncopyable

    class noncopyable  
    {  
    protected:  
        noncopyable (void)  {}  
        ~noncopyable (void)  {  }  
      
    private:
        noncopyable (const noncopyable&);  
        const noncopyable& operator= (const noncopyable&);  
    };

    新特性 8  Alias Template(template typedef)

    功能相当于取别名

    template<typename T>
    using vec = std::vector<T,std::allocator<T>>;
    int main()
    {
        vec<int> v1 {1,2,3,4};
        for(auto i: v1)
        {
            std::cout<< i <<std::endl;
        }
        return 0;
    }


    新特性 9  Type Alias

    类似于typedef,重新命名

    typedef void (*func) (int, int);
    using func = void(*) (int,int);//这两个函数意义相同 但是感觉using更容易让人理解
    template <typename T>
    struct Container {
        using value_type = T; // 相同于 typedef T value_type;
    };

    新特性 10  noexcept,override,final关键字

    //noexcept 保证函数不会丢出异常
    void foo() noexcept; //== void foo() noexcept(true) 括号内处条件  在完成什么条件下不会抛出异常
    void swap(string & x ,string & y) noexcept(noexcept(x.swap(y)))
    {
        x.swap(y);
    }
    
    class MyString
    {
    private:
        char * _data;
        size_t _len;
    
    public:
        //move constructor  move语法必须用noexcept 尤其在vecotr上 不然不让编译 (voctor 是按传进参数个数成长 很容易在申请内存上出错) move意义上当于 by reference
        MyString(MyString&& str)noexcept : _data(str._data), _len(str._len){}
        MyString& operator= (MyString&&str) noexcept {return *this;}
        
    };
    //override 运用在虚函数上 自动识别是否是虚函数
    struct Base
    {
        virtual void vfunc(float){}
    };
    struct Drivedl:Base
    {
        virtual void vfunc(float) override {}//自动识别该函数是否是基类中的虚函数 如果不是报错
    };
    //final 继承树下的最后一个  (没有人可以在继承它)
    struct Base1 final{};//1.作用于类,该类不可被继承 
    struct Base2
    {
        virtual void f() final;//2.作用于函数 该虚函数不可以被重写
    };

    新特性 11  decltype

    相当于type of (识别类型),然编译器去识别type,不能识别重载的函数

    1.基本使用方法

    int main() {
        auto num = 1;  //num 是int类型
        decltype(num) num2 = num; //num2 也是int类型
        return 0;
    }

    2..声明返回值类型

    //判断两个参数相加的返回值类型
    template<typename T1,typename T2>
    auto add(T1 x, T2 y) -> decltype(x+y);

    3. 做参数

    class Person
    {
    public:
        Person(){};
        ~Person(){};
        
    public:
        int m_age = 0;
        std::string lastname  = "";
        std::string firstname = "";
        
    };
    
    auto cmp = [](const Person& p1,const Person& p2)//lambda
    {
        return p1.lastname<p2.lastname||
        (p1.lastname == p2.lastname && p1.firstname< p2.firstname);
    };
    
    int main()
    {
        std::set<Person,decltype(cmp)> coll(cmp);
        Person * p1 = new Person;
        p1->lastname = "a";
        
        Person * p2 = new Person;
        p2->lastname = "b";
        
        Person * p3 = new Person;
        p3->lastname = "c";
        coll.insert(*p3);
        coll.insert(*p1);
        coll.insert(*p2);
        
        for (auto i: coll) {
            std::cout<<i.lastname<<std::endl;
        }
        
        return 0;
    }

      输出结果

     

     参照<<侯捷 C++新标准 C++11>>

     如有不对请指正.

  • 相关阅读:
    asp.net套打
    如何使用哪个asp生成一个excel报表
    自定义打印纸张 c# gdi+ 精确位置打印 套打
    Java调用.dll文件
    [转载].NET实现之(套打解决方案(支持B/S和C/S))
    C#套打
    三十而立,从零开始学ios开发(一):准备起航
    DOTNETBAR的使用方法
    大型网站,要考虑的问题
    AppScan安全漏洞报告
  • 原文地址:https://www.cnblogs.com/LearningTheLoad/p/7192270.html
Copyright © 2020-2023  润新知