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