首页 > 程序人生 > 漫话C++0x(二)

漫话C++0x(二)

本文是《漫话C++0x》系列的第二篇,从本篇开始,我将正式为大家介绍C++0x新增的特性,帮助大家认识C++0x。由于C++0x增加的特性还是挺多的,限于篇幅原因,每一篇只能介绍大概4、5个特性,所以,要把所有的新特性介绍完,需要好几个篇幅。下面言归正传,开始今天要介绍的内容,首先从大家最常用到的基本特性讲起。

  • 1. auto用来声明变量
  • 大家先看看下面的代码,一个我们比较熟悉的C++98中遍历map的例子:

    1
    2
    3
    4
    5
    
    std::map< std::string, std::vector<int> > mp;
    for (std::map< std::string, std::vector<int> >::iterator i = mp.begin(); i != mp.end(); ++i)
    {
        /// traverse the map
    }


    下面再来看一个C++0x改进版的同样的例子:

    1
    2
    3
    4
    5
    
    std::map< std::string, std::vector<int> > mp;
    for (auto i = mp.begin(); i != mp.end(); ++i)
    {
        /// traverse the map
    }

    通过对比,不难发现,用了auto之后,整个代码简洁了很多。其实auto可以用在很多地方,尤其是在复杂的多层嵌套模板中,用auto可以使代码简化不少,这个也是在这里选用map做例子的重要原因。另外auto前后还可以加各种修饰符,看下面的例子:

    1
    2
    3
    4
    5
    
    float data[BufSize];  /// data: float[BufSize]
    auto v3 = data;       /// v3: float*
    auto& v4 = data;      /// v4: float (&)[BufSize]
    auto x1 = 10;         /// x1: int
    const auto *x2 = &x1; /// x2: const int*
  • 2. “>>”可以做为嵌套模板的闭合端,不需要显式的加空格
  • 用过C++模板的朋友应该比较清楚,在C++98中,嵌套模板的闭合的多个”>”之间必须显式的加上空格,要不然编译会不通过,因为C++98的标准认为”>>”这个是右移运算符,用在模板中是非法的。值得大家高兴的是,C++0x已经把这个蹩脚的限制给取消了,以后”>>”也可以用在嵌套模板的闭合端了,没有限制了,请看下面的例子:

    1
    2
    
    std::vector< std::list<int>> vi1;  /// fine in C++0x, error in C++98
    std::vector< std::list<int> > vi2; /// fine in C++0x and C++98
  • 3. 基于范围的loop
  • 在具体介绍这个特性之前,我们首先来看一下,在C++98中,要遍历一个标准的容器是如何做的,这里以vector为例:

    1
    2
    3
    4
    5
    
    std::vector< int> v;
    for (std::vector< int>::iterator i = v.begin(); i != v.end(); ++i)
    {
        /// use iterator i to operate the element in v
    }

    下面再来看一下C++0x的改良版:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    std::vector< int> v;
    for (int num: v) /// for (auto num: v) is also OK
    {
        /// num is the element in v
    }
     
    std::vector< int> v;
    for (int & num: v) /// for (auto & num: v)  is also OK
    {
        /// num is the reference of the element in v
    }

    对比一下,上面的代码比之前的简洁了很多,对于写程序的人来说,能通过简洁的方式实现,决不会用冗长的方式,一方面简洁的方式开发效率要高,另一方面简洁的代码看着也赏心悦目。通过上面的例子,相信大家对基于范围的loop已经有了初步的认为,下面来介绍一下,什么样情况下可以使用基于范围的loop:
    (1)首先,重中之重,基于范围的loop只能用在for loop中,不能用于while, do while的loop
    (2)所有的C++0x中的容器(当然包括C++98中的容器)都可以使用
    (3)可以用在初始化列表和正则表达式的匹配结果(这两个都是C++0x新特性,后面会介绍)
    (4)用户自己定义的类型,如果支持begin(),end()及迭代器遍历也可以用

  • 4. 新增加空指针类型nullptr
  • 我们知道,在C++98中,空指针用NULL表示,而NULL只是define的一个值为0或0L的宏。在大多数情况下,NULL是没有问题的,但是在模板的参数自动推导中,NULL会被推导为int类型,这样就不能匹配指针类型了,请看下面的例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    template< typename F, typename P >
    void DoAndCall(F func, P param)
    {
        /// do something
    	func(param);
    }
    void Func(int * ptr);
    Func(0);       /// ok
    Func(NULL);    /// ok
    Func(nullptr); /// ok
    DoAndCall(Func, 0);       /// error
    DoAndCall(Func, NULL);    /// error
    DoAndCall(Func, nullptr); /// ok

    上面的例子中,传入NULL的时候,NULL被推导为int类型,而Func需要的是一个int *类型的参数,这时候编译就会有问题。也正是因为NULL的这个缺陷,C++0x引入了nullptr这个新的关键字,nullptr的类型是std::nullptr_t,它既具有原来NULL做为空指针的所有特性,还很好的解决了上面提到的问题。

  • 5. unicode的支持,新增加char16_t和char32_t类型
  • c++98支持char和wchar两种字符类型,c++0x为了更好的支持unicode,新增了char16_t和char32_t类型,关于char16_t和char32_t的用法,和char/wchar很类似,看下面的例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    'x'   /// char 'x'
    L'x'  /// wchar_t 'x'
    u'x'  /// char16_t 'x', UCS-2
    U'X'  /// char32_t 'x' UCS-4
     
    /// std::basic_string typedefs for all character types:
    std::string s1;    /// std::basic_string< char>
    std::wstring s2;   /// std::basic_string< wchar_t>
    std::u16string s3; /// std::basic_string< char16_t>
    std::u32string s4; /// std::basic_string< char32_t>
  • 6 原字符串的支持(raw string)
  • 在C++98中,有控制字符和转义字符的概念,像’\n’用来回车等,但有的时候,我们就想把像控制字符这样的特殊字符原样的传输出,不做特殊处理,这时候就需要转义,显得比较麻烦,尤其在正则表达式中,格外突出。C++0x增加了raw string这个概念,也叫原字符串,这样的字符串没有特殊字符,所有的字符都是普通字符,请看下面的例子:

    1
    2
    
    std::string noNewlines(R"(\n\n)");
    std::string cmd(R"(ls /home/docs | grep ".pdf")");

    在上面的例子中,我们看到raw string的语法是 R”(…)”,但是有时候,在正则表达式中,”)会做为匹配的特征,这时候该怎么办呢?C++0x也考虑了这一点,raw string的分隔符可以灵活指定,看下面的例子:

    1
    2
    
    std::regex re1(R"!("operator\(\)"|"operator->")!"); /// "operator()"| "operator->"
    std::regex re2(R"xyzzy("\([A-Za-z_]\w*\)")xyzzy");  /// "(identifier)"

    上面的例子中,第一个例子,用”!(…)!”做了分隔,第二个例子中,用”xyzzy(…)xyzzy”做了分隔,都是因为正规表达式本身就有)”。用户可以指定各种各样的分隔符,原则就是不跟raw string text中的字符不相冲突即可。

    以上即是今天的所有内容,不知道大家有没觉得C++0x带来了让我们眼前一亮的内容,如果是这样子的话,那请继续关注本系列后面的文章吧,更多精彩的内容在后面,谢谢!

    分类: 程序人生 标签: , ,
    1. 2011年9月18日12:44 | #1

      赞!除了干活,平时的小程序已经完全用python了。。。

    2. 2011年9月18日16:53 | #2

      python现在用的人越来越多了,我们测试同事的主流语言就是python。@doubletony

    3. 2011年9月27日15:47 | #3

      raw string好给力啊。感觉越来越轻量级啊~
      求参考链接。

    4. 2011年9月27日21:24 | #4

      wikipedia等,搜一下,挺多的@leon

    5. 2011年10月11日14:38 | #5

      小武哥 :
      wikipedia等,搜一下,挺多的@leon

      搜到某大神的网站了。。

      你的blog现在没有回复邮件通知了?

    6. 2011年10月11日21:55 | #6

      恩,网上挺多的,各种各样的。邮件的插件好像卸了。@leon

    7. 2011年10月11日22:02 | #7

      看了一下,好像是wordpress发不出邮件了,之前的插件还在的。。@leon

    8. 2011年10月11日22:19 | #8

      原来是西数我现在用的这种主机不支持mail,悲催。@leon

    9. 2011年10月13日15:43 | #9

      小武哥 :
      原来是西数我现在用的这种主机不支持mail,悲催。@leon

      悲剧啊~我是用stmp的插件的。。

    1. 本文目前尚无任何 trackbacks 和 pingbacks.
    您必须在 登录 后才能发布评论.