wordpress 4.7.2,网站对图片优化吗,最近重大新闻,网站开发必备技能文章目录 1. C11简介2. 统一的列表初始化2.1 #xff5b;#xff5d;初始化2.2 std::initializer_list 3. 声明3.1 auto3.2 decltype 4. nullptr5. 范围for循环6. 智能指针7. C11STL中的一些变化8. 演示代码 1. C11简介 在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1… 文章目录 1. C11简介2. 统一的列表初始化2.1 初始化2.2 std::initializer_list 3. 声明3.1 auto3.2 decltype 4. nullptr5. 范围for循环6. 智能指针7. C11STL中的一些变化8. 演示代码 1. C11简介 在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1)使得C03这个名字取代了C98称为C11之前的最新C标准名称。 不过由于C03(TC1)主要是对C98标准中的漏洞进行修复语言的核心部分则没有改动因此人们习惯性的把两个标准合并称为C98/03标准。 从C0x到C11C标准10年磨一剑第二个真正意义上的标准珊珊来迟 相比于C98/03C11则带来了数量可观的变化其中包含了约140个新特性以及对C03标准中约600个缺陷的修正这使得C11更像是从C98/03中孕育出的一种新语言。 相比较而言C11能更好地用于系统开发和库开发、语法更加泛化和简单化、更加稳定和安全不仅功能更强大而且能提升程序员的开发效率公司实际项目开发中也用得比较多所以我们要作为一个重点去学习。 C11增加的语法特性非常篇幅非常多我们这里没办法一 一讲解所以最近的几篇文章主要讲解实际中比较实用的语法
官方文档
小故事 1998年是C标准委员会成立的第一年本来计划以后每5年视实际需要更新一次标准C国际标准委员会在研究C 03的下一个版本的时候一开始计划是2007年发布所以最初这个标准叫C 07。但是到06年的时候官方觉得2007年肯定完不成C 07而且官方觉得2008年可能也完不成。最后干脆叫C 0x。x的意思是不知道到底能在07还是08还是09年完成。 结果2010年的时候也没完成最后在2011年终于完成了C标准。所以最终定名为C11。 2. 统一的列表初始化
首先声明一下 这个列表初始化和我们类和对象那里学的初始化列表不是一个概念是不同的。 2.1 初始化
在C98中标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定。 比如 那我们C语言里面其实就是这样搞的嘛所以可以认为C支持这样就是因为要兼容C嘛
那么在C11中 C11扩大了用大括号括起的列表(初始化列表)的使用范围使其可用于所有的内置类型和用户自定义的类型使用初始化列表时可添加等号()也可不添加。 我们来演示一下 大家看C11支持我们这样使用{}初始化并且赋值也可以省略 然后要注意 这样写是咋回事 这是不是可以认为是调int的默认构造啊我们之前说过有了模板之后内置类型也需要有构造函数了。 然后 C11中列表初始化也可以适用于new表达式中 另外 创建对象时也可以使用列表初始化方式调用构造函数初始化 比如我们之前写过的日期类
class Date
{
public:Date(int year, int month, int day):_year(year), _month(month), _day(day){cout Date(int year, int month, int day) endl;}
private:int _year;int _month;int _day;
};2.2 std::initializer_list
那除了上面的场景呢C11还支持了STL里面的容器也可以这样去初始化
比如 都是可以的其它容器也可以大家可以自己试。 那大家思考一下在容器这里它是如何支持可以这样写的呢
首先我们来看一下这个 这里我们直接给一个大括号里面放一些元素这是个啥啊。 之前我们初始化数组可以这样写嘛那它在这里也是一个数组吗 那数组怎么直接赋值给一个vector呢 那不清楚的话我们可以打印看一下它的类型是什么 大家看它的类型是一个叫做initializer_listint的东西。 那为什么这个东西可以赋值给vector呢 大家看红色圈出来的部分C11给STL中的这些容器增加了这样一个构造函数。 支持用initializer_list类型的对象去构造vector这些容器。 所以正常使用这个构造应该是这样写 那我们写成这样 当然也可以因为构造函数支持隐式类型转换嘛。 那initializer_list这个类是个啥呢 initializer_list是C11引入的一种特殊类型用于简化初始化列表的使用。它可以在构造函数或函数参数中以列表的形式传递一组值。 可以认为它就是一个常量数组存储在常量区initializer_list对象中的元素永远是常量值我们无法改变initializer_list对象中元素的值。 这是它的一些接口 那我们接下来做一件事情 我们之前不是模拟实现过STL里面的各种容器的那以vector为例我们来对它改造一下让它也支持用initializer_list进行{}初始化和赋值。 怎么做呢给它增加这个构造函数就行了 每增加之前我们自己的vector肯定是不行的而且大家看这个报错编译器自动就把后面的常量数组识别成initializer list类型了 我们来写一下 这下我们再来运行 就可以了 然后再提一下就是 如果这里用迭代器遍历的话前面加一个typename这个我们之前也提过就是类模板里面直接取内嵌类型它会分不清是类型还是静态成员变量。 当然不止vector可以我们说了C11给STL这几个容器都增加了initializer_list版本的构造 当然除了构造还支持了initializer_list版本的赋值重载 3. 声明
c11提供了多种简化声明的方式
3.1 auto
那auto呢我们在C专栏第一篇文章C入门的时候就介绍过了所以这里就不再重复了
3.2 decltype
再来学一个C11引入的关键字——decltype
什么作用呢 decltype是可以获取表达式或变量类型的关键字 我们之前用过typeid(变量/表达式).name()可以获取变量或表达式的类型然后我们可以打印出来查看而使用decltype我们可以获取类型并使用这个类型 比如 但是大家可能会说 上面的场景用auto也是可以的啊。 确实但是有的场景auto就不行比如 我们要定义一个vector要求vector里面存储的数据类型跟表达式x*y的返回类型一致 大家看这个场景auto就不行了吧 4. nullptr
这个我们之前也介绍过了
5. 范围for循环
也介绍过了
6. 智能指针
关于智能指针我们后面会单独作为一个章节来给大家讲解
7. C11STL中的一些变化
下面我们来分析一下C11中STL与之前相比有了那些变化
首先它增加了一些新容器 用橘色圈起来是C11中的一些几个新容器我们也都介绍过了但是实际最有用的是unordered_map和unordered_set另外两个就显得非常鸡肋 其次呢就是增加了一些新方法 比如提供了cbegin和cend方法返回const迭代器等等但是实际意义不大因为begin和end也是可以返回const迭代器的这些都是属于锦上添花的操作。 实际上C11更新后容器中增加的新方法最实用的就是插入接口函数的右值引用版本 那关于这里3、4两点提到的右值引用和移动语义我们后面也会花大量篇幅给大家讲解…
8. 演示代码
把上面演示过的代码给大家
#define _CRT_SECURE_NO_WARNINGS
#include iostream
using namespace std;//struct Point
//{
// int _x;
// int _y;
//};
//
//int main()
//{
// int a(4);
//
// int b { 2 };
// int c{ 3 };
//
// int arr[]{ 1,2,3,4,5 };
//
// Point p{ 1,2 };
//
// // C11中列表初始化也可以适用于new表达式中
// int* pa new int{ 5 };
// cout *pa endl;
// return 0;
//}//class Date
//{
//public:
// Date(int year, int month, int day)
// :_year(year)
// , _month(month)
// , _day(day)
// {
// cout Date(int year, int month, int day) endl;
// }
//private:
// int _year;
// int _month;
// int _day;
//};
//int main()
//{
// Date d1(2022, 1, 1); // old style
//
// // C11支持的列表初始化这里会调用构造函数初始化
// Date d2 { 2022, 1, 2 };
// Date d3{ 2022, 1, 3 };
// return 0;
//}#include vector
#include list
//int main()
//{
// vectorint v { 1,2,3,4 };
//
// vectorint v2({ 1,2,3,4 });
//
// listint lt { 2,4,6,8,9 };
//
// initializer_listint il { 1,2,3,4,5,6,7,8 };
//
// vectorint v3 il;
//
// return 0;
//}int main()
{const int x 1;double y 2.2;//decltype(x * y) ret; // ret的类型是double//decltype(x) p; // p的类型是const int*auto ret x * y;auto p x;vectordecltype(x* y) v;cout typeid(ret).name() endl;cout typeid(p).name() endl;return 0;
}