} } }

    C++Annoatation 02: More extensions to C , Some fea

    添加时间:2013-5-21 点击量:



    More extensions to C , Some features of C++11



    对于稍微有些C++的同窗,可能都知道C++和C的一些首要差别,大的差别就是一个是面向对象,一个是面向过程,这就涉及到对象; 同时,还有定名空间的引入,防止变量名冲突; 还有struct支撑成员函数等。 我就持续注释一些更须要重视的一些不合,一些是C++11中的器材。

     

    引用

    可以经由过程引用批改它引的对象,然则不克不及改变它本身。这么听来,就像是常量指针, 别的,引用也让代码加倍天然,不像c里边会呈现一堆的&来默示传址调用。





    int a=1;
    int &r=a;
    int const rr = a; // intconst 和
    int&是同一个器材,引用只是一个语法糖。










     


    应用引用时,有几点须要记住:



    引用定义时必须初始化! 其实看上方的法度例子就知道, const的器材都必须初始化

    不要在函数中返回局部变量的引用


    函数中是否应用引用的场合



    引用,可以当做函数参数传入,如许就可能会批改所引用对象。指针也能达到如许的目标,如许多几许少会造成一些困惑,我们可以依从一些原则:

     

    形参是内建类型(int double char等),且我们不须要改变实参值,直接传值调用

    若形参时内建类型,且我们须要批改它,那就经由过程指针调用

     

    形参类型是,布局体等,我们不须要改变它的成员变量,采取 const &
    调用

    形参类型是类等,需要改变,采取引用&调用

     

    应用引用调用,可以或许避免机关函数的调用,节俭开支。

     

    别的,须要实现链式操纵的,返回值选择引用类型,也能避免机关函数的调用。经典例子就是 “cout”

    右值引用 (对C++11不是很熟悉,会有一些懂得上的错误,请斧正)

    C++11中多了个右值引用。 主如果因为姑且变量(右值)不克不及很好的同 const&
    很好的区分隔来,是以C++11多了个右值引用&&。

    举例申明下:



    int intVa()
    {
    return 5;
    }
    int& a = intVal(); // 错误!
    引用姑且变量

    int const& a = intVal(); //
    正确,引用不变姑且变量

    int a = &intVal(); // 错误!
    intVal()不是左值





     

    我们持续看:



    void receive(int& value){++value; cout <<“L-value parameter\n”;} // 左值引用版本
    void receive(int&&
    value){++value; cout << R-value
    parameter\n
    ;} // 右值引用版本
    void
    receive(int const& value)
    {++value; cout << L-value const
    parameter\n
    ;} // ++value不克不及有,不然编译错误。这算是右值引用和const&的差别。





     

    如此调用:



    int main()
    {
    receive(18); //
    R-value 19

    int v = 5;
    int const& cri =
    v;
    receive(cri); // L-value
    const

    receive(v); // L-value
    6

    receive(intVal()); // R-value
    6

    }





     

    若我们把 void receive(int& value)删除,则receive(v) 返回 L-value
    const parameter。 函数重载的右值引用版本匿名变量传入时激发

    别的,右值引用版本函数中,可以对value进行操纵,可以看出,右值引用 用于获取 匿名姑且变量 的 把持权,而 int
    const& 版本的却不可。

    重视下:

    若引入别的个重载版本 void(int value), 那么将产生错误,因为该例中,匿名变量也可以解析成 int
    型,导致重载冲突。

     

    别的,右值引用的进阶应用是 是 移动语义 move semantics 和 完美转发 perfect
    forwarding 的根蒂根基。移动语义我临时还不懂啥,今后再讲述。

    强类型-列举类

    C++中,列举类型其实就是int,不合列举类型可以经由过程static_cast<int>
    来进行斗劲操纵;别的,不合列举类型的内部值不克不及雷同,因为C++中列举类型的感化局限不被列举名所限,而是受感化域限制。

    C++11中,引入了 enum class ,来解决上述题目。





    enum class CharEnum: unsigned char //
    默认是int,可以经由过程这个“:”符号改变

    {
    NOT_OK, // 默认 0
    OK //
    自增1

    };









     

    应用时,要参加列举类名与感化域符,即 CharEnum::OK.

    前向声明如下



    enum Enum1; // Illegal: no size
    available

    enum Enum2: unsigned int; // Legal in C++11:
    explicitly declared type


    enum class
    Enum3; // Legal in C++11: default int type is
    used

    enum class Enum4: char; // Legal in C++11:
    explicitly declared type





    初始化列表

    c说话中,可以用大括号包含一个初始化列表来初始化数组、布局体。C++11把这个概念持续扩大了,引入了 initializer_list<Type>
    这个模本类,可以扩大初始化类,同时也能对初始化列表进行个性化操纵。 应用前,要包含头文件 <initializer_list>
    。同时,可以将初始化列表当做函数形参传入。




    void values(initializer_list<int> iniValues)
    {
    cout << Initializer list having
    << iniValues.size() << values\n;
    for

    initializer_list<int>::const_iterator begin =
    iniValues.begin();
    begin !=
    iniValues.end();
    ++begin

    cout << Value: << begin << \n;
    }







     

    这个常识点Mark下,今后持续深切懂得,记得在 boost 中如同也有类似的器材。

    auto 和 decltype 这个我感觉,好了

    因为C++的声明可能会很是错杂难懂,C++11将曾经的auto关键字,使其可以或许主动解析类型,不错,基于boost的改进。

    auto 和 decltype
    功能异常强大,不过小我认为,还是要把模板常识搞透了再深切应用这个关键字斗劲好,根蒂根基神马的,最首要的了。

     

    int (fun())[10], 默示
    fun是个函数,返回一个指向int数组[10]的指针。如许不好懂得,用上auto后,一切这么天然

    auto func() -> int()[10];

    别的,比如 vector<int>::const_iterator ci = v.begin();
    可以改写成 auto ci = v.begin(); 例子很多,信赖auto的应用,会让C++加倍受迎接。

     

    类型定义和 ‘using’ 声明

     

    比如 unsigned long int compute(double, double),
    这个函数指针的声明,应用typedef可以变成如许:

    typedef unsigned long int(pfun)(double, double);

    然则,我们声明时 pfun f;
    时,袒护了Pfun实际上是一个指针的事实,必须看typedef定义才知道。关于这点,我很诟病,导致我函数指针一向没学好。C++11中将这点进行了升华,采取using
    关键字:



    using pfun =
    unsigned long intdoubledouble);
    或者和auto共同:
    using
    pfun = autodoubledouble
    -> unsigned long
    int;





    for轮回的局限操纵

    传统C/C++ 的for采取标准的
    for(init;cong;next)语句,这对遍历的应用,不那么的便捷,很多说话都供给结局限操纵符,在STL的算法库也包含了for_each办法,然则还是不敷便捷。C++11中引入了for的局限操纵版本:

    int array[100];

    for (auto &element:array){...}

    这里,推荐应用auto,避免思惟肩负在解析类型上。 同时,element是变量名,默示array中每次遍历的元素。
    引用操纵符很是首要,若是要批改元素或array是类类型,则用引用; 若是类类型,但不改变,用const&;
    通俗的内建类型且不改变,可以不消&。

    有了这个局限操纵,C++算是一猛进步呀。

    原始字符串

    传统C/C++应用包含字符串,用\来做逃脱而字符。如许,我们会在代码中看到一堆的\\\\\\
    其实很影响浏览。如今很多说话都支撑正则表达式了,而正则中最多也恰是\\如许的符号,让C++来应用,my god!
    。我感觉C++可能鉴戒了python的R字符串,和perl的定界符规矩,引出本身的原始字符串,在原始字符串中,不存在逃脱语义。写法如下:

    R(string) 写法一

    Rdelimiter(string)delimiter 写法二

    更详尽的论说,筹算放在正则表达式时评论辩论。

     

    新增类型申明符

    ob0101:
    默示二进制的5

    F : 申明是一个浮点型常量 3F

    L : 前缀应用申明字符串中字符是wchar_t, 后缀应用申明是一个 long

    p :十六进制数(2^p), 即左移p。

     

    增长对 Unicode 的支撑



    字符串:
    char utf_8[] = u8This is UTF-8
    encoded.
    ;
    char16_t utf16[] = uThis is UTF-16 encoded.;
    char32_t utf32[] = UThis is UTF-32
    encoded.
    ;







     



    对unicode常量,应用\u逃脱,加上一个十六进制量
    char utf_8[] = u8\u2018;
    char16_t utf16[] = u\u2018;
    char32_t
    utf32[] = U\u2018;








    同样,表达式可以应用原始字符串

    感慨:C++错杂太多了,多了太多器材了,每个常识点都是一大章的器材,看来,路漫漫呀!

     
    彼此相爱,却不要让爱成了束缚:不如让它成为涌动的大海,两岸乃是你们的灵魂。互斟满杯,却不要同饮一杯。相赠面包,却不要共食一个。一起歌舞欢喜,却依然各自独立,相互交心,却不是让对方收藏。因为唯有生命之手,方能收容你们的心。站在一起却不要过于靠近。—— 纪伯伦《先知》
    分享到: