C++ 11中几个我比较喜欢的语法(二)

以前在文章C++ 11中几个我比较喜欢的语法中介绍了几个我比较喜欢的C++语法,其中有些语法因为VC 11还不支持,没法跨平台,因此没有介绍。前几天VS 2013 Preview发布后,对C++ 11又有了一些支持,所以这里继续完成一下C++ 11语法系列:html

原生字符串(raw string literals) c++

不少时候,当咱们只须要一行字符串的时候,字符串转义每每成了一个负担,和写和读都带了很大的不便。例如,对于以下路径"C:\Program Files\Microsoft.NET\ADOMD.NET",咱们必须把它写成以下形式:正则表达式

    string path = "C:\\Program Files\\Microsoft.NET\\ADOMD.NET"; 数组

可能你会说这个并无多大影响,下面这个正则表达式的例子呢?你能看出来原文究竟是什么吗?session

    string exp = "('(?:[^\\\\']|\\\\.)*'|\"(?:[^\\\\\"]|\\\\.)*\")|"; ide

在C#中,咱们能够经过@关键字来取消字符串转义。如今,在C++ 11中,也增长了这样的语法。对于前面的例子,它的非转义形式为:函数

    string path = R"(C:\Program Files\Microsoft.NET\ADOMD.NET)"; ui

从上面的例子中能够看出,它的语法格式以下:this

  1. 字符串前加'R'前缀
  2. 字符串首尾加上括号()

它的语法格式比C#的@前缀要稍微复杂点,不过这个复杂也有复杂的好处,那就是字符串里面能够带引号,例如:spa

    string path = R"(this "word" is escaped)";

而C#就没法保持原始字符串格式,对引号仍须要转义:

    string path = @"this ""word"" is escaped";

 

委托构造函数(Delegating constructors

C++的构造是不能复用的,为了复用其初始化操做,咱们每每会增长一个Initial函数:

    class Foo
    {
    private:
        int A;

    public:
        Foo() : A(0)
        {
            Init();
        }
        Foo(int a) : A(a)
        {
            Init();
        }

    private:
        void Init()
        {
            // do something
        }
    };

这样一来就增长了一个只调用一次的Init函数,而且一旦这个Init函数被其它成员函数调用的话,可能致使重复初始化,也是一个隐患。PS:本例比较简单,经过构造函数默认参数也能够解决构造函数复用问题,但默认参数也有一些局限和带来一些问题,限于篇幅就不作更多的讨论了。

在C++ 11中,引入了委托构造函数的语法,其功能和C#中的this构造函数很是相似,就是语法上稍有差别:

    class Foo
    {
    private:
        int A;

    public:
        Foo() : Foo(0)
        {
        }
        Foo(int a) : A(a)
        {
            // do something
        }
    };

 

初始化列表(initializer list)

在C++ 03中,能够用列表的形式来初始化数组,这种方式很是直观,但只能适用于数组,不能适用于咱们自定义的容器:

    int anArray[5] = { 3, 2, 7, 5, 8 }; // ok

    std::vector<int> vArray = { 3, 2, 7, 5, 8 }; // not ok

在C++ 11中,咱们则可使得咱们自定义的容器对象支持这种列表的形式的初始化方式:

    template <typename T>
    class MyArray
    {
    private:
        vector<T> m_Array;

    public:
        MyArray() { }

        MyArray(const initializer_list<T>& il)
        {
            for (auto x : il)
                m_Array.push_back(x);
        }
    };

    void main()
    {
        MyArray<int> foo = { 3, 4, 6, 9 };
    }

 

统一初始化(Uniform initialization)

C++的对象初始化方式是很是多样的:

    int a = 2;        //"赋值风格"的初始化
    int aa [] = { 2, 3 }; //
用初始化列表进行的赋值风格的初始化
    complex z(1, 2);    //"
函数风格"的初始化

C++ 11中,容许经过以花括号的形式来调用构造函数。这样多种对象构造方式即可以统一块儿来了:

    int a = { 2 };   
    int aa [] = { 2, 3 };  

    complex z = { 1, 2 }; 

值得一提的是,这种花括号的构造方式还能够用于函数的参数和返回值的类型推导,很是简洁。

    void useMyStruct(MyStruct x)
    {
    }
    useMyStruct({ 2, 3.5f });

    MyStruct makeMyStruct(void)
    {
        return { 2, 3.5f };
    }

不过鉴于园子里很多人对C#的var的反感度,估计不少人又要对这种方式高举反对大旗了。

 

VC对C++ 11的支持状况

因为VS 2013仍是Preview阶段,对于c++ 11特性支持仍是不全,在今年发布的RTM版本中还会增长 几个特性:

上到了RTM版本后,主要的经常使用的特性基本上都支持了。剩余的部分,则会在后续的版本中给予支持,以下是VC的RoadMap:http://video.ch9.ms/sessions/build/2013/2-306.pptx,连C++ 14的支持计划也列出来了。整体上感受MS仍是仍是比较给力的。

相关文章
相关标签/搜索