当前位置: 首页 > news >正文

C++11(1)

目录

前言

小故事

C++11优势

统一的列表初始化

1.{}初始化

2. std::initializer_list

声明

1.auto

2.decltype

 3.nullptr


前言

小故事

1998 年是 C++ 标准委员会成立的第一年,本来计划以后每 5 年视实际需要更新一次标准, C++ 国际
标准委员会在研究 C++ 03 的下一个版本的时候,一开始计划是 2007 年发布,所以最初这个标准叫
C++ 07 。但是到 06 年的时候,官方觉得 2007 年肯定完不成 C++ 07 ,而且官方觉得 2008 年可能也
完不成。最后干脆叫 C++ 0x x 的意思是不知道到底能在 07 还是 08 还是 09 年完成。结果 2010 年的
时候也没完成,最后在 2011 年终于完成了 C++ 标准。所以最终定名为 C++11

C++11优势

C++11是继1998年的后更新的C++大版本;C++11对比C++98带来了数量可观的变化,增加了很多新特性。相比较而言C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多。所以对C++11的学习是很重要的。

这里是C++11的具体内容C++11 - cppreference.com,有兴趣的可以看看;

统一的列表初始化

1.{}初始化

C++98 中,标准允许使用花括号 {} 对数组或者结构体元素进行统一的列表初始值设定。比如:
创建对象时也可以使用列表初始化方式调用构造函数初始化;
struct Point
{
int _x;
int _y;
};
int main()
{
int array1[] = { 1, 2, 3, 4, 5 };
int array2[5] = { 0 };
Point p = { 1, 2 };
return 0;
}
C++11 扩大了用大括号括起的列表 ( 初始化列表 ) 的使用范围,使其可用于所有的内置类型和用户自
定义的类型, 使用初始化列表时,可添加等号 (=) ,也可不添加
struct Point
{int _x;int _y;
};
int main()
{int x1 = 1;int x2{ 2 };int array1[]{ 1, 2, 3, 4, 5 };int array2[5]{ 0 };Point p{ 1, 2 };// C++11中列表初始化也可以适用于new表达式中int* pa = new int[4]{ 0 };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// C++11支持的列表初始化,这里会调用构造函数初始化Date d2{ 2022, 1, 2 };Date d3 = { 2022, 1, 3 };return 0;
}

C++支持一切即可列表初始化,并且可以省略赋值符号;

2. std::initializer_list

小问题:date d={2024,9,4};和vector<int>v={2024,7,25};的{}有什么区别?

这两个{}本质上是不一样的,date d的{}会调用它的构造函数初始化d,而date类中只有三个参数,所以{}中只能有3个数;但是vector就不一样了,vector的{}中的元素数量是可变化的,并不是固定的三个;同样其他的容器list等也是如此;因此传递的参数是一个数组来进行初始化;为了方便统一,所以就出现了initializer_list的数组容器来统一作为数组参数;

std::initializer_list的介绍文档: https://cplusplus.com/reference/initializer_list/initializer_list/ 
在vector和list的底层实现拷贝构造时也使用到了initializer_list当参数来接收数组;我们可以使用列表模拟一个数组来看下其类型;
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>using namespace std;int main()
{auto it = { 1,2,3 };//it就是initializer_list的类型的cout << typeid(it).name() << endl;       return 0;
}

我们会发现数组的类型就是initializer_list而且是个模版;因此我们可以把initializer_list看成是一个{}形式的数组容器;

那么initializer_list底层到底是什么呢?
其实initializer_list是一个容器;这个容器包含了两个指针;一个指向数组的头部,一个指向数组的尾部;
然后还提供了迭代器操作;我们可以来验证一下;

 我们从调试中可以看出的确是包含了两个指针,分别指向数组的头和尾,而且提供了迭代器操作;另外我创建了一个局部变量,我们都知道局部变量是创建在栈上的,通过对比数组的地址和局部变量的地址我们可以推断出initializer_list是在栈上开辟的数组;

{}和initializer_list的优势体现:

例子:

	map <string, string >mp = { {"apple","苹果"},{"banana","香蕉"},{"sort","排序"} };

分析:这个mp初始化使用了{}和initializer_list的结合;{"apple","苹果"}等是调用了pair<string ,string>的构造函数,最外层就是initializer_list;整体来看就是个pair<string,string>类型的数组;这样的好处就是不需要多次的创造pair<string,string>的临时变量进行初始化,极大的方便了c++玩家;

声明

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

1.auto

auto 可以自动的推导变量的类型,一般用于替代代码较长的类型或范围for循环中;
需要注意的是auto 后不可以用于函数参数或者返回类型;

int main()
{
int i = 10;
auto p = &i;
auto pf = strcpy;
cout << typeid(p).name() << endl;
cout << typeid(pf).name() << endl;
map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
//map<string, string>::iterator it = dict.begin();
auto it = dict.begin();
return 0;
}

2.decltype

// decltype的一些使用使用场景
template<class T1, class T2>
void F(T1 t1, T2 t2)
{
decltype(t1 * t2) ret;
cout << typeid(ret).name() << endl;
}
int main()
{
const int x = 1;
double y = 2.2;
decltype(x * y) ret; // ret的类型是double
decltype(&x) p;      // p的类型是int*
cout << typeid(ret).name() << endl;
cout << typeid(p).name() << endl;
F(1, 'a');
return 0;
}

decltype也可以推导出变量的类型,但是与typeid不同的是他可以作为类型本身来使用;而typeid只能以字符串的形式打印出来;相比之下decltype更加的灵活;

 3.nullptr

由于 C NULL 被定义成字面量 0 ,这样就可能回带来一些问题,因为 0 既能指针常量,又能表示
整形常量。所以出于清晰和安全的角度考虑, C++11 中新增了 nullptr ,用于表示空指针。
#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *)0)
#endif
#endif

C中的问题:这是在C++文件中的一段代码,两个函数的参数分别是int和int*,当实参是NULL时是可以调用第一个函数的,因为C中define了NULL是0;如果要调用第二个函数是不是就需要传实参为指针类型,我们就需要传参数((void*)0);这个在C中发生类型转换把0转换为int*的;但是在C++中是不支持void*转换的;所以就出现了问题;因此C++中支持nullptr为空指针;
今天的文章到这里就结束啦,我后续会继续补充的;

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 力扣刷题(4)
  • 日系编曲:日系架子鼓写作思路 支点音符 幽灵音 抢拍(重音移位)半速与倍速
  • Kotlin 范型之协变、逆变、不变
  • Springboot-文件的上传和下载
  • 解析 MySQL 数据库的 Python 接口:`mysqlclient` 与 `django-mysql` 实战指南20240904
  • ArcGIS展线/投线教程
  • idea 编译断点运行 tomcat 10.1.28 源码
  • redis的一些重要的基础知识
  • onvif应用--IPC鉴权(认证)
  • Linux起源
  • matlab基本语法
  • windows安装composer
  • 网恋照妖镜源码搭建教程
  • LINUX常用命令-docker-Kubernetes
  • 【机器人工具箱Robotics Toolbox开发笔记(二)】Matlab中机器人工具箱的下载与安装
  • [译]前端离线指南(上)
  • 4. 路由到控制器 - Laravel从零开始教程
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • CSS实用技巧
  • gf框架之分页模块(五) - 自定义分页
  • js对象的深浅拷贝
  • linux安装openssl、swoole等扩展的具体步骤
  • SpiderData 2019年2月13日 DApp数据排行榜
  • vue:响应原理
  • 包装类对象
  • 笨办法学C 练习34:动态数组
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 翻译--Thinking in React
  • 解决iview多表头动态更改列元素发生的错误
  • 前端面试总结(at, md)
  • 听说你叫Java(二)–Servlet请求
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​学习笔记——动态路由——IS-IS中间系统到中间系统(报文/TLV)​
  • ######## golang各章节终篇索引 ########
  • #AngularJS#$sce.trustAsResourceUrl
  • #pragma once与条件编译
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (六)激光线扫描-三维重建
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (轉貼) 寄發紅帖基本原則(教育部禮儀司頒布) (雜項)
  • (状压dp)uva 10817 Headmaster's Headache
  • .Net Core 笔试1
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .net MVC中使用angularJs刷新页面数据列表
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .NET 使用配置文件