【C++】语法简化和增强,C++11都做了什么?
目录1、统一的列表初始化1.2 std::initializer_list2、声明2.1 auto2.2 decltype2.3 nullptr2.4 constexpr结语相比于C98C11在C98的基础上进行了大量的改进和扩展包含了很多新特性也包括对一些缺陷的修正这些新特性和改进不仅提高了代码的质量和效率还为开发者提供了更强大的工具和更灵活的编程方式。1、统一的列表初始化C11支持一切皆可列表初始化。在C98中我们可以对数组和结构体用{}进行初始化C11扩大了{}的使用范围使其可以对所有内置类型和自定义类型初始化可是说是统一了列表的初始化方式。其中初始化列表时是可以省略的。structPoint{int_a;int_b;};intmain(){inta1;intb{2};intarr1[]{1,2,3};intarr2[]{4,5,6};Point{7,8};//c11中列表初始化也适用new表达式int*pnewint[1]{0};return0;}C11也支持创建对象时使用列表初始化调用构造函数初始化。classDate{public:Date(intyear,intmonth,intday):_year(year),_month(month),_day(day){}private:int_year;int_month;int_day;};intmain(){Dated1(2024,10,18);Date d2{2024,10,18};Date d3{2024,10,18};return0;}上面的初始化方式和容器的初始化方式很像但两者有本质的区别要分清楚。intmain(){Date d3{2024,10,18};vectorintv{2024,10,18};return0;}自定义类型{}初始化时必须和构造参数个数匹配容器{}初始化可以有任意多个参数1.2 std::initializer_liststd::initializer_list是C11引入的一种特殊类型它提供了一种简洁、直观的方式来初始化容器或数组以及作为函数特别是构造函数的参数来接受多个同类型的值。std::initializer_list提供了迭代器可以通过begin()和end()成员函数获取指向列表首元素和尾元素不包括尾元素本身的迭代器。作为函数参数特别是当函数需要处理多个同类型参数时使用std::initializer_list可以使函数接口更加简洁和灵活。| 列表初始化和initializer_list的区别和联系区别列表初始化是一种初始化方式而initializer_list是一种类型列表初始化使用大括号{}来包围初始化器的值而initializer_list则是一个模板类用于接收这些值联系当使用列表初始化语法时编译器会生成一个std::initializer_list对象来存储初始化列表中的元素类的构造函数可以重载以接受一个std::initializer_list类型的参数从而允许使用列表初始化来创建对象2、声明2.1 autoC11后auto关键字用于自动类型推断这意味着编译器会根据初始化表达式来自动确定变量的类型。这个特性使得对一些长类型更加方便。intmain(){std::mapstd::string,std::stringm{{front,前},{behind,后}};//std::mapstd::string, std::string::iterator it m.begin();autoitm.begin();return0;}2.2 decltypedecltype关键字将变量的类型声明为表达式指定的类型。假如我们想用vector存map的迭代器//vectorstd::mapstd::string, std::string::iterator v;vectordecltype(it)v;这个时候用decltype就很方便。2.3 nullptrNULL实际是一个宏C中NULL可能被定义为字面常量0或者C中被定义为无类型指针(void*)的常量不论采取何种定义在使用空值的指针时都不可避免的会遇到一些麻烦本想通过f(NULL)调用指针版本的f(int*)函数但是由于NULL被定义成0调用了f(int x)因此与程序的初衷相悖f((void*)NULL)调用会报错C11中引入nullptrnullptr是一个特殊的关键字nullptr是一种特殊类型的字面量它可以转换成任意其他类型的指针类型使用nullptr定义空指针可以避免类型转换的问题因为nullptr只能被隐式地转换为指针类型而不能被转换为整数类型2.4 constexpr字面含义const常量、exprexpression表达式。常量表达式—— 在编译期就能计算出结果的值。让编译器在编译阶段完成计算而不是等到运行时。constexprintsquare(intx){returnx*x;}intmain(){constexprintresultsquare(5);// 编译期计算result 25intarr[result];// 编译期常量可用作数组大小return0;}constvsconstexpr特性constconstexpr修饰对象变量、成员函数、指针变量、函数、构造函数保证运行时不可修改编译期常量初始化时机运行时或编译期必须编译期初始化函数不能修饰普通函数可以修饰函数编译期求值intx10;constintax;// ✅ 合法运行时初始化之后不可改constexprintbx;// ❌ 非法x 不是编译期常量constexprintc42;// ✅ 合法编译期常量constintdc;// ✅ 合法d 也是编译期常量C11 的constexpr函数只能有一条 return 语句// C11 合法constexprintsquare(intx){returnx*x;}// C11 非法多条语句constexprintsum(intn){intresult0;// ❌ 不能有局部变量for(inti1;in;i)resulti;// ❌ 不能有循环returnresult;}那 C11 能做什么简单的数学计算constexprintfactorial(intn){returnn1?1:n*factorial(n-1);// 递归单表达式}constexprintffactorial(5);// 120编译期常量替代宏constexprdoublePI3.141592653589793;constexprdoubleE2.718281828459045;编译期数组大小constexprintSIZE100;intarr[SIZE];// 合法结语本文只介绍了C11带来的一些语法简化和增强后面会重点介绍C11的新特性和功能Lambda表达式、智能指针、多线程支持、右值引用等等敬请期待。本篇文章的分享就到这里了如果您觉得在本文有所收获还请留下您的三连支持哦~