• C++11--20分钟了解C++11 (上)


    20分钟了解C++ 11

    1 初始化列表 Initializer List

    
    //C++ 03中用初始化列表初始化数组
    int arr[4] = {3, 2, 4, 5};
    
    vector<int> v;
    v.push_back(3);
    v.push_back(2);
    v.push_back(4);
    v.push_back(5);
    
    
    
    // C++ 11 做了扩展,可以初始化vector
    vector<int> v = {3, 4, 1, 9};   // 调用初始化列表构造函数
    // 所以相关的STL容器都更新了,支持初始化列表
    
    
    
    // 定义自己的初始化列表构造函数:
    #include <initializer_list>
    class BoVector {
       vector<int> m_vec;
       public:
       BoVector(const initializer_list<int>& v) {
          for (initializer_list<int>::iterator itr = v.begin(); itr!=v.end(); ++ itr)
             m_vec.push_back(*itr);
       }
    };
    
    BoVector v = {0, 2, 3, 4};
    BoVector v{0, 2, 3, 4};   // 初始化的另一种方式
    
    
    // 自动进行常规的初始化
    class Rectangle {
       public:
       Rectangle(int height, int width, int length){ }
    };
    
    void draw_rect(Rectangle r);
    
    int main() {
       draw_rect({5, 6, 9});  // Rectangle{5,6,9}被自动调用
    }
    
    // 注意:要小心使用
    // 1. 可读性非常差,即使有IDE的帮助也是。函数名称很少表示函数所采用的参数类型
    // 2. 函数可以被不同参数类型重载,比如下面的情况
    
    void draw_rect(Triangle t);
    

    2 统一初始化Uniform Initialization

    // C++ 03
    class Dog {     // 聚合类或者结构体,直接初始化对应成员
       public:
          int age;
          string name;
    };
    Dog d1 = {5, "Henry"};   // 可以直接用大括号聚合初始化
    
    // C++ 11 扩展了大括号初始化的范围
    class Dog {
       public:
          Dog(int age, string name) {...};
    };
    Dog d1 = {5, "Henry"};  //类有合适参数的构造函数
    
    
    /* 统一初始化的搜索顺序:
     * 1. 初始化列表构造函数
     * 2. 具有合适参数的常规构造函数
     * 3. 聚合初始化(直接初始化对应成员)
     */
    
    Dog d1{3};
    
    class Dog {
       public:
       int age;                                // 第3选择
    
       Dog(int a) {                            // 第2选择
          age = a;
       }
    
       Dog(const initializer_list<int>& vec) { // 第1选择
          age = *(vec.begin());      
       }
    };
    

    3 auto类型

    std::vector<int> vec = {2, 3, 4, 5};
    
    // C++ 03
    for (std::vector<int>::iterator it = vec.begin(); it!=vec.end(); ++ it)
        m_vec.push_back(*it);
    
    
    // C++ 11: 使用auto节省大量打字的时间
    for (auto it = vec.begin(); it!=vec.end(); ++ it)
        m_vec.push_back(*it);
    
    auto a = 6;    // a is a integer
    auto b = 9.6;  // b is a double
    auto c = a;    // c is an integer
    auto const x = a;   // int const x = a
    auto& y = a;        // int& y = a
    
    // 它是静态类型,没有运行时成本,fat-free.
    // 使得代码更易维护
    
    // 1. 当需要类型转换时不要使用auto
    // 2. IDE变得很重要
    

    4. foreach

     */
    // C++ 03:
       for (vector<int>::iterator itr = v.begin(); itr!=v.end(); ++ itr)
          cout << (*itr);
    
    
    // C++ 11:
       for (auto i: v) { // 任何有begin()和end()的类都能使用
          cout << i ;    // 只读访问
       }
    
       for (auto& i: v) {
          i++;                 // 改变v的值,避免拷贝构造
       }                       
    
       auto x = begin(v);  // 同int x = v.begin();
    
       int arr[4] = {3, 2, 4, 5};
       auto y = begin(arr); // y == 3
       auto z = end(arr);   // z == 5
       // 因为数组定义了begin()和end()
       // 可以通过给数据的容器定义begin()和end(),使你的代码适配第三方库
    

    5 nullptr

     * 代替C++ 03中的NULL
     */
    // NULL具有二义性
    void foo(int i) { cout << "foo_int" << endl; }
    void foo(char* pc) { cout << "foo_char*" << endl; }
    
    int main() {
       foo(NULL);    // 二义性,调用哪个函数?
    
       // C++ 11
       foo(nullptr); // 调用foo(char*)
    }
    

    6 枚举类 enum class

    
       // C++ 03
       enum apple {green_a, red_a};
       enum orange {big_o, small_o};
       apple a = green_a;
       orange o = big_o;
    
       if (a == o) //两个不同枚举类型进行比较
          cout << "green apple and big orange are the same
    ";
       else
          cout << "green apple and big orange are not the same
    ";
    
    
       // C++ 11
       enum class apple {green, red};
       enum class orange {big, small};
       apple a = apple::green;
       orange o = orange::big;
    
       if (a == o)  //编译失败,因为我们没有定义 ==(apple, orange)
          cout << "green apple and big orange are the same
    ";
       else
          cout << "green apple and big orange are not the same
    ";
    

    7 static_assert

    
    // 运行时断言
       assert( myPointer != NULL );
    
    // C++ 11提供了静态断言,在编译时检查
    // 如果int的大小不是4,编译不过
       static_assert( sizeof(int) == 4 );
    

    8 委托构造函数

    
    // 一个构造函数想复用另一个构造函数的代码
    // 下面这种方法是错误的,会构造两个对象
    class Dog {
       public:
       Dog() { ... }
       Dog(int a) { Dog(); doOtherThings(a); }
    };
    
    
    // C++ 03的实现方法:
    class Dog {
       init() { ... };
       public:
       Dog() { init(); }
       Dog(int a) { init(); doOtherThings(); }
    };
    /* 缺点:
     * 1. 代码笨重.
     * 2. 而且init()可能被其他函数调用
     */
    
    // C++ 11 方法:
    class Dog {
       int age = 9;
       public:
       Dog() { ... }
       Dog(int a) : Dog() { doOtherThings(); }
    };
    // 限制: Dog()也即被委托的构造函数必须先被调用
    
  • 相关阅读:
    iOS sqlite数据库使用
    vsts 自动部署到Azure
    中国区的Azure添加到 VSTS 的 Service Endpoint
    修改vs17中的cordova模板
    升级vs17中的cordova-simulate
    cordova 从xcode7迁移到xcode8
    自杀程序&递归删除目录
    如何升级cordova插件
    在ubuntu on windows 上安装jekyll
    gitphp日期乱码解决方案
  • 原文地址:https://www.cnblogs.com/logchen/p/10193374.html
Copyright © 2020-2023  润新知