• C++11(列表初始化,声明,范围for)


    目录

    一、列表初始化

    1、一般的列表初始化

     2、容器的列表初始化

    二、声明

    1、 auto

    2、decltype

    3、nullptr

     三、 范围for


    一、列表初始化

    1、一般的列表初始化

    在C++98中,标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定。

    1. int main()
    2. {
    3. int array1[] = { 1, 2, 3, 4, 5 };
    4. int array2[5] = { 0 };
    5. return 0;
    6. }

    而在C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加。

    注:new 表达式初始化时一定不能写等号。

    1. int main()
    2. {
    3. int x1 = 1;
    4. int x2{ 2 };
    5. int array1[]{ 1, 2, 3, 4, 5 };
    6. int array2[5]{ 0 };
    7. int* pa = new int[4]{ 0 };
    8. return 0;
    9. }

    创建对象时也可以使用列表初始化方式调用构造函数初始化。如下图的d2和d3。

    1. class Date
    2. {
    3. public:
    4. Date(int year, int month, int day)
    5. :_year(year)
    6. ,_month(month)
    7. ,_day(day)
    8. {
    9. cout << "Date(int year, int month, int day)" << endl;
    10. }
    11. private:
    12. int _year;
    13. int _month;
    14. int _day;
    15. };
    16. int main()
    17. {
    18. Date d2{ 2022, 1, 2 };
    19. Date d3 = { 2022, 1, 3 };
    20. return 0;
    21. }

     2、容器的列表初始化

    在 vector 和 list 这样的容器中,如果我们需要插入数据的话,我们就要通过 push_back 这样的函数去一个一个插入。但是,在c++11中,我们可以通过如下方式去插入数据:(等号也可以省略)。

    1. vector<int> v1 = { 1,2,3,4 };
    2. list<int> lt1 = { 1,2,3,4,5,6,7 };

    这种插入的方式就非常方便,那么这种方式是怎么实现的呢?实现这种方式,就需要一个新的容器 了,这个容器叫 initializer_list。

    它是C++11新增的容器,提供了 begin 和 end 函数,用于迭代器遍历;以及获取容器中的元素个数的 size 函数。

    C++在语法层面会把 { } 认成 initializer_list,下面我们来看一看{ }的类型是什么:

    1. auto x = { 1,2,3,4,5,6 };
    2. cout << typeid(x).name() << endl;

    从上图中我们发现该变量的类型就是 initializer_list 。

    那么我们再来看一看vector的构造:

    上面的(3)就是实现了 initializer_list ,这样就使得我们可以像上面那样对容器进行构造。

    当用列表对容器进行初始化时,会被认为是initializer_list类型,此时不管有多少个值都能够被初始化vector,而以前我们必须使用 push_back 一个一个将元素插入。

    所以现在有了C++11列表初始化的功能,我们也可以给我们自己之前模拟实现的vector和list容器加上这个功能,下面我就来给vector加上这个功能。

    实现思路:遍历initializer_list 中的元素,然后push_back进要初始化的容器当中。

    1. vector(initializer_list il)
    2. :_start(nullptr)
    3. , _finish(nullptr)
    4. , _endofstorage(nullptr)
    5. {
    6. typename initializer_list::iterator it = il.begin();
    7. while (it != il.end())
    8. {
    9. push_back(*it);
    10. ++it;
    11. }
    12. }

    二、声明

    1、 auto

    在C++98中auto是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,所以auto就没什么价值了。C++11中废弃auto原来的用法,将其用于实现自动类型推断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初始化值的类型。

    我们直接来使用一下它: 

    1. int main()
    2. {
    3. int i = 10;
    4. auto p = i;
    5. cout << "i: " << typeid(i).name() << endl;
    6. cout << "p: " << typeid(p).name() << endl;
    7. map dict = { {"sort", "排序"}, {"insert", "插入"} };
    8. //map::iterator it = dict.begin();
    9. auto it = dict.begin();
    10. cout << "it: " << typeid(it).name() << endl;
    11. return 0;
    12. }

    2、decltype

    关键字decltype将变量的类型声明为表达式指定的类型,即:根据表达式的实际类型推演出定义变量时所用的类型。

    上面我们用到的 typeid 也能够推导出变量的类型,那么它们有什么区别呢?

    typeid拿到的只是类型的字符串,不能用这个再去定义对象。下面的定义方式就不正确。

    typeid(x).name() y = 20    //这样定义y不行

     decltype 则可以推导出一个变量的类型,然后再去定义新的变量。如下图:

    1. int x1 = 10;
    2. decltype(x1) y1 = 20; //可以这样去定义y1

    3、nullptr

    由于C++中NULL被定义成字面量0,这样就可能回带来一些问题,因为0既能指针常量,又能表示整形常量。所以出于清晰和安全的角度考虑,C++11中新增了nullptr,用于表示空指针。 其定义如下:

    1. #ifndef NULL
    2. #ifdef __cplusplus
    3. #define NULL  0
    4. #else
    5. #define NULL  ((void *)0)
    6. #endif
    7. #endif

     三、 范围for

    1. int main()
    2. {
    3. string s("hello world");
    4. string::iterator it = s.begin();
    5. while (it != s.end())
    6. {
    7. cout << *it << " ";
    8. it++;
    9. }
    10. cout << endl;
    11. for (auto e : s)
    12. {
    13. cout << e << " ";
    14. }
    15. cout << endl;
    16. }

     上面两种遍历方式的结果完全相同。这是因为范围for本质上是迭代器,在代码编译的时候,编译器会自动将范围for替换为迭代器的形式去遍历。

  • 相关阅读:
    asp.net core获取config和env
    vue课程77 使用解构赋值
    HDU_7149
    行车记录仪E-mark认证要如何办理?
    s21.云原生发展经历的阶段与未来发展趋势
    在服务器 和 虚拟机中 查看代码 samba source insight
    Dockerfile基础
    基于weixin小程序乡村旅游系统的设计
    spark SQLQueryTestSuite sql 自动化测试用例
    Transformer面试十问
  • 原文地址:https://blog.csdn.net/zdlynj/article/details/132701045