zoukankan      html  css  js  c++  java
  • [C++11新特性]第二篇

    0.可变数量参数,可变函数模版,变长模版类

    • c++98可变数量参数

    #include<cstdio>
    #include<cstdarg>
    double SumOfFloat(int count, ...)
    {
        va_list ap;
        double sum=0;
        va_start(ap,count);
        for(int i=0;i<count;i++)
            sum+=va_arg(ap,double);
        va_end(ap);
        return sum;
    }
    int main()
    {
        printf("%f
    ",SumOfFloat(3,1.2f,3.4,5.6));
        return 0;
    }
    • 可变函数模版

    #include<iostream>
    #include<stdexcept>
    using namespace std;
    void Print(const char *s)
    {
        while(*s){
            if(*s=='%'&&*++s!='%')
                throw runtime_error{"missing arguments"};
            cout<<*s++;
        }
    }
    template<typename T,typename...Args>
    void Print(const char*s,T value,Args...args)
    {
        while(*s)
        {
            if(*s=='%'&&*++s!='%')
            {
                cout<<value;
                return Print(++s,args...);
            }
            cout<<*s++;
        }
        throw runtime_error{"extra arguments provided to Print"};
    }
    int main()
    {
        Print("hello %s
    ",string("world"));
        return 0;
    }
    • 变长模版类

    #include<iostream>
    using namespace std;
    
    template<long...nums> struct Multiply;
    
    template<long first,long ...last>
    struct Multiply<first,last ...>
    {
        static const long val=first*Multiply<last...>::val;
    };
    template<>
    struct Multiply<>
    {
        static const long val=1;
    };
    int main()
    {
        cout<<Multiply<2,3,4,5>::val<<endl;
        cout<<Multiply<22,44,66,88,9>::val<<endl;
        return 0;
    }

    1.C++11原子类型

    在并行编程、多线程编程中,对于共享资源的访问,需要通过添加互斥锁的方法来保证正确性。在POSIX标准下,pthread库,我们用lock方法来实现,如下:

    pthread_mutex_t m=PTHREAD_MUTEX_INITIALIZER;
    
    void* func(void*)
    {
        long long i;
        for(i=0;i<10000000;i++)
        {
            pthread_mutex_lock(&m);
            total+=i;
            pthread_mutex_unlock(&m);
        }
    }

    而在c++11中,我们通过定义的原子类型即可很方便地实现。c++11定义很多原子数据类型,比如:atomic_bool,atomic_char,atomic_int等等。

    //total定义为原子类型,c++11中不需要为原子类型声明互斥锁
    atomic_llong total{0};
    void func(int)
    {
        for(long long i=0;i<100000;i++)
            total+=i;
    }

    2.内存模型,顺序一致性与memory_order

    太复杂,主要是硬件平台下内存读写顺序一致性.在c++11中,实现了很多内存顺序的细节,比如顺序一致、松散、release-require、release-consume四种顺序模型。

    3.线程局部存储

    本节省略…….

    4.指针空值

            在良好的编程习惯中,声明一个变量时,同时初始化,在以前的习惯里,如果声明指针,一般初始化为0或NULL。

    其中NULL为宏定义,在stddef.h中可见细节,一般被定义为0或(void*)常量。

    在c++11中,定义了一个指针空值类型的常量:nullptr,大小和void*一致。另有nullptr_t常量。

    5.默认函数的控制

    在c++中声明自定义类,编译器会自动生成默认函数:构造函数、拷贝构造函数、拷贝赋值函数、移动构造函数、移动拷贝函数、析构函数。

    还会自动生成默认操作符:operator,,operator&,operator&&,operator*,operator->,operaotr->*,operator new,operator delete.

    在以前的c++编程规则中,如果我们指定带参数的构造函数,则需要重写不带参数,即默认构造函数。

    class TwoCstor
    {
        //提供了带参数的构造函数,则必须自行提供不带参数的版本
        public:
            TwoCstor(){};
            TwoCstor(int i):data(i){};
        private:
            int data;
    }

    在C++11中,通过default关键字来实现这个目标。如下:

    class TwoCstor2
    {
        //提供了带参数的构造函数,再指示编译器提供默认版本
        public:
            TwoCstor2()=default;
            TwoCstor2(int i):data(i){};
        private:
            int data;
    }

            在实现Singleton模式中,我们需要将拷贝构造函数设为私有,在c++11中则更简单,直接利用deleted关键字,指示编译器不生成函数的默认版本。

    #include<type_traits>
    #include<iostream>
    using namespace std;
    class NoCopyCstor
    {
        public:
            NoCopyCstor()=default;
            //通过使用"=delete"有效阻止用户错用拷贝构造函数
            NoCopyCstor(const NoCopyCstor &)=delete;
    };
    int main()
    {
        NoCopyCstor a;
        NoCopyCstor b(a);//无法通过编译
    }

    6.lambda函数

    lambda函数的语法定义如下:

         [capture](parameters) mutable –>return-type {statement}

    使用lambda函数作为stable_sort函数的调用对象。

    int main()
    {
        vector<string> strVec{"hello","wo","panzg1","at3","binary_function"};
        stable_sort(strVec.begin(),strVec.end(),
            [](const string &a,const string &b){return a.size()<b.size();});
        for(auto e : strVec)
            cout<<e<<endl;
    }

    code…各种各样的lambda函数

    捕获列表的常见几种形式:

    • [var] 值传递捕获var
    • [=]值传递方式捕获所有父作用域的变量,包括this
    • [&var]引用传递捕获var
    • [&]引用传递捕获所有父作用域的变量,包括this
    • [this] 值传递方式捕获当前this指针

    值传递、引用传递可以混用,比如[=,&a,b]等等。

    仿函数,functor,函数对象,就i是重定义了成员函数operator()的一种自定义类型对象。比如在下面的例子中,test不是一样函数,而是一个对象。仿函数广泛地被用在STL中,在c++11中lambda也要被广泛使用。

    #include<iostream>
    class _functor
    {
        public:
            int operator()(int x,int y) {return x+y;}
    };
    int main()
    {
        _functor test;
        int x=3,y=4;
        std::cout<<test(3,4);
    }

    事实上,仿函数是编译器实现lambda的一种方式,在现阶段,通常编译器会把lambda函数转化为一个仿函数对象。

    关于lambda和STL的联系,它使得STL的算法使用更加方便,比如for_each,其原型是:

    UnaryProc for_each(InputIterator beg,InputIterator end,UnaryProc op)

    for_each算法第三个参数是一个单个参数的“函数”,即一个函数指针、仿函数或者lambda函数。

    函数指针方法的缺陷是:往往定义在别的地方,阅读代码不方便;如果不进行inline优化,性能就比lambda函数差很多。而且函数指针的应用范围小很多,相比函数指针、仿函数,lambda函数往往是最佳的选择。

    注:在c++98中,STL帮助我们定义了很多仿函数可直接使用。

  • 相关阅读:
    ViewDragHelper: ViewDragHelper的使用
    HashMap存入和取出数据顺序不一致
    服务器raid卡、磁盘缓存的配置策略
    关于LVS+Nginx为什么会被同时使用的思考
    JDT Icons-eclipse图标大全
    EclipseHTML/JS/CSS/JS 代码自动提示
    eclipse maven设置本地仓库
    mysql 补零操作(zerofill)
    mysql datetime字段默认值 设置 当前时间
    Timed out as no activity
  • 原文地址:https://www.cnblogs.com/panweishadow/p/3694883.html
Copyright © 2011-2022 走看看