• C++11列表初始化


    列表初始化:
    1.旧语法中定义了初始化的几种不同形式,如下:
    int data = 0; //赋值初始化
    int data = {0}; //花括号初始化
    int data(0); //构造初始化
    int data{0}; //花括号初始化

    2.C++11以旧语法中花括号初始化形式为基础,设计了列表初始化语法,统一了不同的初始化形式。
    数据类型 变量{初始化列表}

    #include <iostream>
    #include <iterator>
    using namespace std;
    
    struct Student
    {
        char name[256];
        struct Date
        {
            int year;
            int month;
            int day;
        }bday;
    };
    
    class Complex
    {
    public:
        Complex(double r = 0, double i = 0) :m_r(r), m_i(i) {}
        friend ostream& operator<<(ostream &os, Complex const &that)
        {
            return os << that.m_r << "+" << that.m_i << "i";
        }
        Complex(Complex const &that) :m_r(that.m_r), m_i(that.m_i)
        {
            cout << "拷贝构造函数" << &that << "->" << this << endl;
        }
    private:
        double m_r, m_i;
    };
    
    int main()
    {
        int a{ 123 };
        cout << a << endl;
        double b{ 3.4567 };
        cout << b << endl;
        int c[]{ 100, 200, 300 };
        copy(c, c + sizeof(c) / sizeof(c[0]), ostream_iterator<decltype(*c)>(cout, " "));
        cout << endl;
        Student d{ "张飞",{ 2000, 1, 1 } };
        cout << d.name << "," << d.bday.year << "-" << d.bday.month << "-" << d.bday.day << endl;
        Complex e{ 1.2, 3.4 };
        cout << e << endl;
        Complex *f = new Complex{ 1.2, 3.4 };
        cout << *f << endl;
        delete f;
        f = new Complex[3]{ { 1.1, 2.2 },{ 2.2, 3.3 },{ 3.3, 4.4 } };
        copy(f, f + 3, ostream_iterator<decltype(*f)>(cout, " "));
        cout << endl;
        delete[] f;
        cout << Complex{ 1.2, 3.4 } << endl;
        //Complex const (&h)[3]{{ 1.1, 2.2 }, { 2.2, 3.3 }, { 3.3, 4.4 }};
        Complex const h[3]{ { 1.1, 2.2 },{ 2.2, 3.3 },{ 3.3, 4.4 } };
        copy(h, h + 3, ostream_iterator<decltype(*h)>(cout, " "));
        cout << endl;
        Complex i = e;
        //Complex i = Complex(1.2, 3.4);
        cout << i << endl;
        return 0;
    }

    3. 变长初始化表,initializer_list

    #include <iostream>
    #include <iterator>
    #include <vector>
    #include <map>
    using namespace std;
    
    class A
    {
    public:
        A(initializer_list<int> li)
        {
            for (auto it = li.begin(); it != li.end(); ++it)
            {
                m_vi.push_back(*it);
            }
        }
        friend ostream &operator<<(ostream &os, A const &that)
        {
            copy(that.m_vi.begin(), that.m_vi.end(), ostream_iterator<decltype(that.m_vi[0])>(os, " "));
            return os;
        }
    private:
        vector<int> m_vi;
    };
    
    int average(initializer_list<int> scores)
    {
        if (!scores.size())
            return 0;
        int sum = 0;
        for (auto it = scores.begin(); it != scores.end(); ++it)
            sum += *it;
        return sum / scores.size();
    }
    
    int main()
    {
        char const *a[]{ "张飞", "赵云", "关羽", "黄忠", "马超" };
        copy(a, a + sizeof(a) / sizeof(a[0]), ostream_iterator<decltype(a[0])>(cout, " "));
        cout << endl;
        vector<const char *> b{ "张飞", "赵云", "关羽", "黄忠", "马超" };
        copy(b.begin(), b.end(), ostream_iterator<decltype(b[0])>(cout, " "));
        cout << endl;
        map<const char *, int> c{ { "张飞", 100 },{ "赵云", 50 },{ "关羽", 25 } };
        for (auto it = c.begin(); it != c.end(); ++it)
            cout << it->first << ":" << it->second << endl;
        /*for (map<const char *, int>::iterator it = c.begin(); it != c.end(); ++it)
        cout << it->first << ":" << it->second << endl;*/
        A a1{ 1, 3, 5, 7, 9 };
        cout << a1 << endl;
        A a2{ 2,4,6,8,10 };
        cout << a2 << endl;
        int d = 60, e = 70, f = 80;
        cout << average({ d,e,f }) << endl;
        cout << average({ 50,d, e, f,90 }) << endl;
        getchar();
        return 0;
    }

    4.聚合类型
    (4.1)任意类型的数组
    (4.2)满足特定条件的类:
    a 无自定义的构造函数
    b 无私有或者保护的非静态成员变量
    c 无基类
    d 无虚函数
    e 无通过“=”或者“{}”在类声明部分被初始化的非静态成员变量
    (4.3)聚合类型的元素或者成员可以是聚合类型也可以是非聚合类型
    (4.4)对聚合类型使用列表初始化,相当于对其中的元素逐一初始化,
    而对非聚合类型使用列表初始化,相当于用列表初始化的值作为参数,调用相应的构造函数。

    5.initializer_list作为轻量级的列表容器,不但可以用在构造函数中,
    也可以作为普通函数的参数,传递不定数量的实参,相对于传统标准容器,
    效率更高(轻量级列表容器,仅保存初始化列表元素的引用,而非其副本)

    #include <iostream>
    #include <iterator>
    #include <list>
    using namespace std;
    
    //轻量级列表容器内部存放初始化列表元素的引用而非其拷贝
    initializer_list<int> light(void)
    {
        int a = 1000, b = 2000, c = 3000;
        //返回局部变量的引用将在函数返回以后失效
        return{ a,b,c };
    }
    
    //重量级容器内部存放初始化列表元素的拷贝而非其引用
    list<int> heavy(void)
    {
        int a = 1000, b = 2000, c = 3000;
        //所返回局部变量拷贝在函数返回后继续有效
        return{ a, b, c };
    }
    
    int main()
    {
        //可以接受任意长度的初始化列表,但列表中元素的类型必须相同
        initializer_list<int> initlist{ 10, 20, 30, 40, 50, 60 };
        //initilizer_list只有三个公有成员:begin,end,size
        copy(initlist.begin(), initlist.end(), ostream_iterator<decltype(*initlist.begin())>(cout, " "));
        cout << "[" << initlist.size() << "]" << endl;
    
        //迭代器为只读类型,其目标元素不可修改
        /*for (auto it = initlist.begin(); it != initlist.end();++it)
        {
        *it *= 100;
        }*/
    
        //可以对容器整体赋值
        initlist = { 100, 200, 300 };
        copy(initlist.begin(), initlist.end(), ostream_iterator<decltype(*initlist.begin())>(cout, " "));
        cout << "[" << initlist.size() << "]" << endl;
        //提供缺省构造函数,用于实例化空容器
        initlist = {};
        copy(initlist.begin(), initlist.end(), ostream_iterator<decltype(*initlist.begin())>(cout, " "));
        cout << "[" << initlist.size() << "]" << endl;
        initlist = light();
        copy(initlist.begin(), initlist.end(), ostream_iterator<decltype(*initlist.begin())>(cout, " "));
        cout << "[" << initlist.size() << "]" << endl;
        list<int> li = heavy();
        copy(li.begin(), li.end(), ostream_iterator<decltype(*li.begin())>(cout, " "));
        cout << "[" << li.size() << "]" << endl;
        return 0;
    }

    6.列表初始化可以防止类型收窄,即对可能造成信息损失的类型转换,提示警告或者直接报错
    long double ld = 3.1415926;
    int a{ld},b{ld}; //error,转换未执行,因为存在丢失信息的危险
    int a(ld),b(ld); //true,转换执行,且确实丢失了部分值

  • 相关阅读:
    linux基础命令:alias
    linux基础命令:find
    Linux下which、whereis、locate命令的区别
    逆元知识普及(进阶篇) ——from Judge
    BZOJ 3620: 似乎在梦中见过的样子
    HDU contest808 ACM多校第7场 Problem
    P3203 [HNOI2010]弹飞绵羊 —— 懒标记?分块?LCT?...FAQ orz
    可持久化数组(线段树)[模板题]
    可持久化并(xian)查(duan)集(shu)
    主席树(静态)的轻松入门
  • 原文地址:https://www.cnblogs.com/LuckCoder/p/8467656.html
Copyright © 2020-2023  润新知