语法甜点11:非成员的begin和end

http://www.cnblogs.com/hujian/archive/2012/12/07/2807941.html


    语法甜点11:非成员的begin和end
    在C++ 03中,标准容器都提供了begin和end成员函数,但对于普通数组,则只能使用不同的写法。比如:

1 vector<int> v; 
2 int a[100]; 
3 sort(v.begin(), v.end()); 
4 sort(a, a+sizeof(a)/sizeof(a[0]));
    为了统一语法,C++ 11提供了非成员的begin和end函数。用法如下:
1 sort(begin(v), end(v)); 
2 sort(begin(a), end(a));
   
    语法甜点12:显式虚函数重载    
    在引入C++ 11之前,基类和派生类中的虚函数很容易产生错误使用的情况。比如:
    a、基类添加了一个虚函数,但该虚函数与派生类中的某个已有普通函数相同。
    b、派生类添加了一个普通函数,但该函数与基类中的某个已有虚函数相同。
    为了避免这些情况,在C++ 11中可以使用override来显式地表明需要进行虚函数重载。比如:
复制代码
 1 class Base 
 2 {
 3     virtual void some_func(float);
 4 };
 5 
 6 class Derived : public Base
 7  {
 8     virtual void some_func(int) override;        // 将产生编译错误
 9    virtual void some_func(float) override;    // 正确
10 };
复制代码
    注意:为了保持向后兼容,此功能是选择性的。
    C++ 11中还引入了final指示符,用于防止类或接口被继承。比如:
复制代码
 1 class  Base1 final { };
 2 class Derived1 : public Base1 { };            // 将产生编译错误
 3 class Base2
 4 {
 5     virtual void f() final;
 6 };
 7 class Derived2 : public Base2
 8 {
 9     void f();                                             // 将产生编译错误
10 };
复制代码
   
    语法甜点13:强类型枚举
    在C++ 03中,枚举类型不是类型安全的。枚举类型被视为整数,这使得两种不同的枚举类型之间可以进行比较。C++ 03唯一提供的安全机制就是一个整数或一个枚举型值不能隐式转换为另一个枚举型值。
    在C++ 11中,引入了enum class来声明类型安全的枚举类型。比如:
enum class IColor1 { Red, Blue, Gree=100, Black };
    IColor1不能隐式地转换为整数类型,也不能与整数类型比较大小。使用枚举名时,必须明确指定其所属范围,比如:必须使用IColor1::Red,而不能单独使用Red。
    在C++ 11中,使用enum class和传统的enum时,还可以指定其所用的数据类型,不指定时默认为int。比如:
1 enum class IColor2 : unsigned int { Red, Blue, Gree=100, Black };
2 enum IColor3 : unsigned int { Red, Blue, Gree=100, Black };
    另外,在C++ 03中,无法对枚举类型进行前置声明。而在C++ 11中,只要是使用了指定数据类型的新式枚举,都可以进行前置声明。比如:
1 enum class IColor1;
2 enum class IColor2 : unsigned int;
3 enum IColor3 : unsigned int;
   
    语法甜点14:模板别名
    在C++ 03中,可以使用typedef给模板类指定一个新的类型名称,但却不能给类模板指定别名。比如:
1 template< typename first, typename second, int third>
2 class SomeType;   template< typename second>
3 typedef SomeType<OtherType, second, 5> TypedefName;  // 在C++ 03中是不合法的
    为了能够定义类模板的别名,C++ 11允许像下面这样使用using关键字:
1 template< typename first, typename second, int third>
2 class SomeType;
3 template< typename second>
4 using TypedefName = SomeType<OtherType, second, 5>;
    另外,using也能定义一般类型的别名,此时等同于typedef。比如:
1 typedef void (*Func)(int);
2 using  Func = void (*)(int);
    
    语法甜点15:无限制的union
    在C++ 03中,并非任意的数据类型都能做为union的成员。比方说,带有non-trivial构造函数的类型就不能是 union 的成员。在C++ 11中,移除了所有对union的使用限制,除了其成员仍然不能是引用类型这种情况。 
复制代码
 1 struct point
 2 {
 3      point() {}
 4      point(int x, int y): m_x(x), m_y(y) {}
 5      int m_x, m_y;
 6 };
 7 union
 8 {
 9      int z;
10      double w;
11      point p;                     // 在C++ 03中不合法;在C++ 11中合法
12 };
复制代码
    备注:C++ 03中不适合做union成员变量的情形有以下几种:
        1、类或结构体中含有non-trival的构造函数(拷贝构造函数)、析构函数、拷贝赋值操作符、虚函数等。
        2、类的基类和成员变量中含有1中所述几个函数。
        3、静态变量。
        4、变量引用。
 
    语法甜点16:新的字符串字面值
    C++ 03提供了两种字符串字面值。第一种,包含有双引号,产生以空字符结尾的const char数组。第二种,有着前标L,产生以空字符结尾的const wchar_t数组,其中wchar_t代表宽字符。C++ 03不支持Unicode编码。
    在C++ 11中,为了加强C++编译器对Unicode的支持,类别char的定义被修改为其大小至少能够存储UTF-8的8位编码,并且能够容纳编译器的基本字符集的任何成员。
    C++ 11 支持三种Unicode编码方式:UTF-8,UTF-16,和UTF-32。除了上述char定义的变更, C++ 11还增加了两种新的字符类别:char16_t和char32_t,用于存储UTF-16和UTF-32的字符。
    下面展示了如何产生使用这些编码的字符串字面值:
1 u8"I'm a UTF-8 string."
2 u"This is a UTF-16 string."
3 U"This is a UTF-32 string."
    第一个字符串的类型是通常的const char[],第二个字符串的类型是const char16_t[],第三个字符串的类型是const char32_t[]。 
    为了避免在字符串中频繁使用转义字符的麻烦,C++11还提供了raw字符串字面值。比如:
1 R"(The String Data \ Stuff " )"
2 R"delimiter(The String Data \ Stuff " )delimiter"
    raw字符串字面值能够和宽字面值或Unicode字面值结合起来使用,比如:
1 u8R"XXX(I'm a "raw UTF-8" string.)XXX"
2 uR"*@(This is a "raw UTF-16" string.)*@"
3 UR"(This is a "raw UTF-32" string.)"
    
    语法甜点17:sizeof
    在C++ 11中,允许sizeof运算符作用在类型的数据成员上,而无须明确的对象。在C++ 03中,这是不允许的,会导致编译错误。比如:
1 struct SomeType { OtherType member; };
2 sizeof(SomeType::member);        // 在C++ 03中不合法;在C++ 11中合法
 
    语法甜点18:新的算法
    C++ 11中新增了一些比较实用的算法。比如all_of、any_of、none_of、copy_n、copy_if和iota等。参考代码如下:
复制代码
1 int a[5] = {-2, -1, 0, 1, 2};
2 auto funIsPositive = [](int v){return v>0;};
3 bool bRet = all_of(a, a+5, funIsPositive);             // false
4 bRet = any_of(a, a+5, funIsPositive);                  // true
5 bRet = none_of(a, a+5, funIsPositive);                // false
6 int b[5] = {0};
7 copy_n(a, 5, b);                                                // 将a开始的5个元素拷贝到b中
8 copy_if(a, a+5, b, funIsPositive);                        // 将1, 2两个数拷贝到b中
9 iota(a, a+5, 10);                                               // a中的每个元素加10
复制代码
    
    语法甜点19:泛化的常数表达式
    C++ 03中本来就已经具有常数表示式的概念,比如:3+5,6*7等。常数表示式对编译器来说是优化的机会,编译器常在编译期运行它们并且将值存入程序中。同样地,在许多场合下,C++规范要求使用常数表示式。比如数组大小、枚举值等。
    然而,常数表示式总是在遇到了函数调用时就终结。比如:
1 int GetFive() { return 5; }
2 int some_value[GetFive() + 5];         // 不合法
    C++ 11引进关键字constexpr允许用户保证函数是编译期常数。比如:
1 constexpr int GetFive() { return 5; }
2 int some_value[GetFive() + 5];
    
    语法甜点20:包装引用
    包装引用类似于一般的引用。对于任意对象,我们可以通过模板类ref得到一个包装引用 (至于常引用,则可以通过 cref 得到)。考虑下面的代码:
复制代码
1 void f (int &r)  { r++; }
2 template<class F, class P> void g (F f, P t)  { f(t); }
3 
4 int n = 0 ;
5 g(f, n) ;
6 cout << n << endl;                     // 輸出0
7 g(f, ref(n));
8 cout << n << endl;                     // 輸出1
复制代码
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值