• C++11特性


    C++11简介

    相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率。

    列表初始化

    {}初始化

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

    1. struct Point
    2. {
    3. int _x;
    4. int _y;
    5. };
    6. int main()
    7. {
    8. int array1[] = { 1, 2, 3, 4, 5 };
    9. int array2[5] = { 0 }; //0 0 0 0 0
    10. Point p = { 1, 2 }; //运用了struct结构体的语法 初始化
    11. return 0;
    12. }

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

    1. struct Point
    2. {
    3. int _x;
    4. int _y;
    5. Point(int x, int y)
    6. :_x(x)
    7. , _y(y)
    8. {}
    9. };
    10. class Date
    11. {
    12. public:
    13. Date(int year, int month, int day)
    14. :_year(year)
    15. , _month(month)
    16. , _day(day)
    17. {
    18. cout << "Date(int year, int month, int day)" << endl;
    19. }
    20. private:
    21. int _year;
    22. int _month;
    23. int _day;
    24. };
    25. int main()
    26. {
    27. Point p = { 1, 2 };
    28. //Point p{ 1, 2 };
    29. Point* p3 = new Point[3]{ {1, 1}, { 2, 2 }, { 3, 3 } };
    30. int* p1 = new int(0);
    31. int* p2 = new int[5]{1,2,3,4,5};
    32. //C++11中 new可以初始化数组
    33. //自定义类型的列表初始化
    34. Date d1(2022, 3, 13);
    35. Date d2 = { 2022, 3, 15 };
    36. Date d3{ 2022, 3, 15 };
    37. Date{2022,3,15};
    38. int i = 1;
    39. int j = { 2 };
    40. int k{ 3 };
    41. return 0;
    42. }

    总结:

    • C++11里面扩展了{}初始化使用,基本都可以使用它来初始化
    • 但是建议还是按旧的用法来使用,一般new[]建议使用它来初始化

    std::initializer_list

    模拟实现的vector支持{}初始化和赋值:

    1. template<class T>
    2. class vector
    3. {
    4. public:
    5. typedef T* iterator;
    6. vector(initializer_list l)
    7. {
    8. _start = new T[l.size()];
    9. _finish = _start + l.size();
    10. _endofstorage = _start + l.size();
    11. iterator vit = _start;
    12. typename initializer_list::iterator lit = l.begin();
    13. while (lit != l.end())
    14. {
    15. *vit++ = *lit++;
    16. }
    17. //for (auto e : l)
    18. // *vit++ = e;
    19. }
    20. vector& operator=(initializer_list l) {
    21. vector tmp(l);
    22. std::swap(_start, tmp._start);
    23. std::swap(_finish, tmp._finish);
    24. std::swap(_endofstorage, tmp._endofstorage);
    25. return *this;
    26. }
    27. private:
    28. iterator _start;
    29. iterator _finish;
    30. iterator _endofstorage;
    31. };

     std::initializer_list使用场景:
    std::initializer_list一般是作为构造函数的参数,C++11对STL中的不少容器(像map、vector、list)就增加std::initializer_list作为参数的构造函数,这样初始化容器对象就更方便了。也可以作为operator=的参数,这样就可以用大括号赋值

     

    1. class A
    2. {
    3. public:
    4. A(int a, double d, int b)
    5. :_a(a)
    6. , _d(d)
    7. , _b(b)
    8. {}
    9. private:
    10. int _a;
    11. double _d;
    12. int _b;
    13. };
    14. class Date
    15. {
    16. public:
    17. Date(int year, int month, int day)
    18. :_year(year)
    19. , _month(month)
    20. , _day(day)
    21. {
    22. cout << "Date(int year, int month, int day)" << endl;
    23. }
    24. private:
    25. int _year;
    26. int _month;
    27. int _day;
    28. };
    29. int main()
    30. {
    31. //内置类型的列表初始化
    32. vector<int> v1 = { 1, 2, 3, 4, 5 };
    33. vector<int> v2{ 1, 2, 3, 4, 5 };
    34. //vector (initializer_list il,const allocator_type& alloc = allocator_type());
    35. auto lt1 = {1, 2, 3, 4};
    36. initializer_list<int> lt2 = { 1, 2, 3, 4 };
    37. //auto=initializer_list
    38. mapint> dict1 = { pairint>("sort", 1), pairint>("insert", 2) };
    39. mapint> dict2 = { { "sort", 1 }, { "insert", 2 } };
    40. //首先{ "sort", 1 }, { "insert", 2 }创建成initializer_list>类型的对象
    41. //最后map (initializer_list il,const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());
    42. //这个构造函数初始化dict2
    43. //自定义类型的列表初始化
    44. Date d1(2022, 3, 13);
    45. Date d2 = { 2022, 3, 15 };
    46. Date d3{ 2022, 3, 15 };
    47. Date{ 2022, 3, 15 };
    48. A aa1 = { 1, 1.11, 1};

    总结:

    • 一个自定义类型调用{}初始化,本质是调用对应的构造函数
    • 自定义类型对象可以使用{}初始化,必须要要有对应参数类型和个数的构造函数
    • STL容器支持{}初始化,容器支持一个initializer_list作为参数的构造函数

    声明

    c++11提供了多种简化声明的方式,尤其是在使用模板时。

    auto(在C++中不支持C语言中原来auto的用法)

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

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

     

    decltype

    关键字decltype将变量的类型声明为表达式指定的类型

    1. // decltype的一些使用使用场景
    2. template<class T1, class T2>
    3. void F(T1 t1, T2 t2)
    4. {
    5. decltype(t1 * t2) ret = t1 * t2;
    6. vector<decltype(t1* t2)> v;
    7. v.push_back(ret);
    8. cout << typeid(ret).name() << endl;
    9. }
    10. int main()
    11. {
    12. int i = 10;
    13. auto p = &i;
    14. auto pf = strcpy;
    15. decltype(pf) pf1; //char * (__cdecl*)(char *,char const *)
    16. vector<decltype(pf)> v;
    17. cout << typeid(p).name() << endl;
    18. cout << typeid(pf).name() << endl;
    19. return 0;
    20. }

    注意:decltype与auto的差别:auto必须要求显式初始化,而decltype没要求

    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

  • 相关阅读:
    布隆过滤器(Bloom Filter)
    SeaTunnel 2.3.4 Cluster in K8S
    前端网页开发实例入门
    【C++】:类和对象(中)之拷贝构造函数+赋值运算符重载
    阿里云&腾讯云服务器安装oracle11g
    【通关MySQL】Java的JDBC编程
    JS标准库
    Redis实战篇(六)附近商铺、用户签到、UV统计
    日联科技在科创板过会:上半年营收约2亿元,宁德时代等为股东
    10.Tomcat,Servlet
  • 原文地址:https://blog.csdn.net/m0_72572822/article/details/126755542