目录
四、新增加容器---静态数组array、forward_list以及unordered系列
一、C++11简介
在
2003
年
C++
标准委员会曾经提交了一份技术勘误表
(
简称
TC1)
,使得
C++03
这个名字已经取代了
C++98
称为
C++11
之前的最新
C++
标准名称。不过由于
C++03(TC1)
主要是对
C++98
标准中的漏洞
进行修复,语言的核心部分则没有改动,因此人们习惯性的把两个标准合并称为
C++98/03
标准。
从
C++0x
到
C++11
,
C++
标准
10
年磨一剑,第二个真正意义上的标准珊珊来迟。
相比于
C++98/03
,
C++11
则带来了数量可观的变化,其中包含了约
140
个新特性,以及对
C++03
标准中
约
600
个缺陷的修正,这使得
C++11
更像是从
C++98/03
中孕育出的一种新语言
。相比较而言,
C++11
能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更
强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多,所以我们要作为一个
重点去学习
。
C++11
增加的语法特性篇幅非常多,我们这里没办法一 一讲解,所以本节课程
主要讲解实际中比较实用的语法。
二、列表初始化
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,1,2,3 };
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;
}
2.std::initializer_list
std::initializer_list的介绍文档:
http://www.cplusplus.com/reference/initializer_list/initializer_list/
std::initializer_list是什么类型:
int main()
{
// the type of il is an initializer_list<int>
auto il = { 10, 20, 30 };
cout << typeid(il).name() << endl;
return 0;
}
此类型的对象由编译器根据初始化列表声明自动构造,该声明是用大括号括起来的逗号分隔元素的列表
该类型内部由两个指针构成,_First指向第一个元素的地址,_Last指向最后一个元素后一个位置的地址
initializer_list内部实现了迭代器,可以用范围for打印initializer_list
std::initializer_list
一般是作为构造函数的参数,
C++11
对
STL
中的不少容器就增加
std::initializer_list
作为参数的构造函数,这样初始化容器对象就更方便了。也可以作为
operator=
的参数,这样就可以用大括号赋值。
三、变量类型推导
1.auto
在
C++98
中
auto
是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局
部的变量默认就是自动存储类型,所以
auto
就没什么价值了。
C++11
中废弃
auto
原来的用法,将
其用于实现自动类型推断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初
始化值的类型。
int main()
{
int i = 10;
auto p = &i;
cout << typeid(p).name() << endl;
map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
//map<string, string>::iterator it = dict.begin();
auto it = dict.begin();
return 0;
}
2.decltype
关键字
decltype
将变量的类型声明为表达式指定的类型。
// decltype的一些使用使用场景
template<class T1, class T2>
void F(T1 t1, T2 t2)
{
decltype(t1 * t2) ret;//ret的类型是int
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;
}
3.nullptr
由于
C++
中
NULL
被定义成字面量
0
,这样就可能回带来一些问题,因为
0
既能指针常量,又能表示
整形常量。所以出于清晰和安全的角度考虑,
C++11
中新增了
nullptr
,用于表示空指针。
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
四、新增加容器---静态数组array、forward_list以及unordered系列
用橘色圈起来是
C++11
中的一些几个新容器,但是实际最有用的是
unordered_map
和
unordered_set
。其他的大家了解一下即可。
1.静态数组 array
array文档
C++设计这个容器对标的是C语言的静态数组,但是因为C++的动态数组vector完全可以代替array,所以array这个容器设计的意义并不大
int main()
{
array<int,10> a1;
vector<int> a2(10);
return 0;
}
2.单链表 forward_list
forward_list为单链表,里面只实现了尾插和尾删,没list好用,感兴趣可以阅读文档进行学习。
3.unordered_map
1. unordered_map 是存储 <key, value> 键值对的关联式容器,其允许通过 keys 快速的索引到与其对应的 value 。2. 在 unordered_map 中,键值通常用于惟一地标识元素,而映射值是一个对象,其内容与此键关联。键和映射值的类型可能不同。3. 在内部 ,unordered_map 没有对 <kye, value> 按照任何特定的顺序排序 , 为了能在常数范围内找到 key 所对应的 value , unordered_map 将相同哈希值的键值对放在相同的桶中。4. unordered_map 容器通过 key 访问单个元素要比 map 快,但它通常在遍历元素子集的范围迭代方面效率较低。5. unordered_maps 实现了直接访问操作符 (operator[]) ,它允许使用 key 作为参数直接访问value 。6. 它的迭代器至少是前向迭代器。
接口说明:
1) unordered_map的构造
函数声明 | 功能介绍 |
unordered_map |
构造不同格式的
unordered_map
对象
|
2) unordered_map的容量
函数声明
|
功能介绍
|
bool empty() const
|
检测
unordered_map
是否为空
|
size_t size() const
|
获取
unordered_map
的有效元素个数
|
3)
unordered_map
的迭代器
函数声明 | 功能介绍 |
begin |
返回
unordered_map
第一个元素的迭代器
|
end |
返回
unordered_map
最后一个元素下一个位置的迭代器
|
cbegin |
返回
unordered_map
第一个元素的
const
迭代器
|
cend |
返回
unordered_map
最后一个元素下一个位置的
const
迭代器
|
4)unordered_map的元素访问
函数声明 | 功能介绍 |
operator[] |
返回与
key
对应的
value
,没有返回一个默认值
|
注意:该函数中实际调用哈希桶的插入操作,用参数
key
与
V()
构造一个默认值往底层哈希桶
中插入,如果
key
不在哈希桶中,插入成功,返回
V()
,插入失败,说明
key
已经在哈希桶中,
将
key
对应的
value
返回。
5)
unordered_map
的查询
函数声明 | 功能介绍 |
iterator find(const K& key) |
返回
key
在哈希桶中的位置
|
size_t count(const K& key) |
返回哈希桶中关键码为
key
的键值对的个数
|
注意:
unordered_map
中
key
是不能重复的,因此
count
函数的返回值最大为
1
6)
unordered_map
的修改操作
函数声明 | 功能介绍 |
insert |
向容器中插入键值对
|
erase |
删除容器中的键值对
|
void clear() |
清空容器中有效元素个数
|
void swap(unordered map&) |
交换两个容器中的元素
|
7)
unordered_map
的桶操作
函数声明 | 功能介绍 |
size_t bucket count()const |
返回哈希桶中桶的总个数
|
size_t bucket size(size_t n)const |
返回
n
号桶中有效元素的总个数
|
size_t bucket(const K& key) |
返回元素
key
所在的桶号
|
4.unordered_set
参见文档:unordered_set文档
unordered_map和unordered_set查找效率高的原因是因为其底层是由哈希表构建的,我们之前对哈希表有过讲解,大家感兴趣看去进我主页学习,之后我会继续对C++11的其他内容进行讲解,这篇博客先到此结束。