十一、 表达式
如果处于某种原因,要将一条语句放到两行中,可以在第一行末尾添加反斜杠 \,否则会出错。
左值通常是内存单元,右值可以使内存单元的内容。
因此所有的左值都可用作右值,但并非所有的右值都可用作左值。
例如365 = year;
不合理
逻辑运算符合按位运算的差别在于,按位运算符返回的并不是布尔值,而是对操作数对应位执行指定运算的结果。
移位运算符(<<、>>)将整个位序列向左或向右移动,其用途之一是将数据乘以或除以2n。
三目操作符:
?:
例如:
int max = (num1 > num2) ? num1 : num2;
等同于:
int max;
if (num1 > num2)
{max = num1;}
else
{max = num2;}
基于范围的for循环
for (VarType varNmae : sequence)
{}
例如给定一个数组:
int someNums[] = {1, 2, 3};
for (int a : someNums)
cout << a << endl;
就可以把数组的每个元素输出。
十二、标准模板库
1、顺序容器
顺序容器按照顺序存储数据,如数组和列表。顺序容器具有插入速度快但查找操作相对较慢的特征。
- std::vector :操作和动态数组一样,在最后插入数据;可将vector看做书架,可在一段添加和拿走图书。
- std::deque :与std::vector类似,但允许在开头插入好热删除元素。
- std::list : 操作和双向链表一样。可看做链条,对象被连接在一起,可以在任何位置添加或者删除对象。
- std::forward_list :类似于std:list,但是单向链表,只能沿着一个方向遍历。
2、关联容器
关联容器按指定的顺序存储数据,就像字典一样。这将降低插入数据的速度,但在查询方面有很大的优势。
- std::set : 存储各不相同的值,在插入时进行排序;容器的复杂度为对数。
- std::unordered_set :存储各不相同的值,在插入时排序;容器的复杂度为常数。这种容器是c++11新增的。
- std::map : 存储键-值对,并根据唯一的键排序;容器的复杂度为对数。
- std::unordered_map :存储键-值对,并根据唯一的键排序;容器的复杂度为对数。
- std::multiset :与set类似,但允许存储多个值相同的项,即值不需要是唯一的。
- std::unordered_multiset :与unordered_set类似,但允许存储多个值相同的项,即值不需要是唯一的。
- std::multimap:与map类似,但是不要求键是唯一的。
- std::unordered_multimap:与unordered_map类似,但不要求键是唯一的。
3、容器适配器
容器适配器是顺序容器和关联容器的变种,其功能有限,用于满足特定的需求。
- std::stack :以LIFO(last in first out 后进先出)的方式存储元素,让我们能在栈顶插入和删除元素。
- std::queue:以FIFO(first in first out 先进先出)的方式存储元素,让我们能删除最先插入的元素。
- std::priority_queue:以特定顺序存储元素,因为优先级最高的元素总是在队列的开头。
4、迭代器
迭代器是一种检查容器内元素并遍历元素的数据类型。可以替代下标访问vector对象的元素。每种容器类型都定义了自己的迭代器类型,如 vector:
vector<int>::iterator iter;
上述语句定义了一个名为 iter 的变量,它的数据类型是 vector< int > 定义的 iterator 类型。每个标准库容器类型都定义了一个名为 iterator 的成员,这里的 iterator 与迭代器实际类型的含义相同。
(1)STL string 类
拼接字符串
sting sampleStr1 ("Hello");
string sampleStr2 ("String");
sampleStr1 += sampleStr2;
或
sampleStr1.append(sampleStr2);
都可以把"Hello"和"String" 链接起来。
查找
size_t charPos = sampleStr.find ("day", 0);
if (charPos != string :: npos)
cout ....
else
cout ....
size_t在32位架构上是4字节,在64位架构上是8字节,在不同架构上进行编译时需要注意这个问题。而int在不同架构下都是4字节,与size_t不同;且int为带符号数,size_t为无符号数。
ssize_t是有符号整型,在32位机器上等同与int,在64位机器上等同与long int.
size_t一般用来表示一种计数,比如有多少东西被拷贝等。例如:sizeof操作符的结果类型是size_t,该类型保证能容纳实现所建立的最大对象的字节大小。 它的意义大致是“适于计量内存中可容纳的数据项目个数的无符号整数类型”。所以,它在数组下标和内存管理函数之类的地方广泛使用。
而ssize_t这个数据类型用来表示可以被执行读写操作的数据块的大小.它和size_t类似,但必需是signed.意即:它表示的是signed size_t类型的。
截断
erase()
string sampleStr ("Hello String! Wake up to a beautiful day !);
sampleStr.erase (13, 28); // 删除从第13个到第28个字符。
sampleStr.erase(iCharS); //删除指定的字符 iCharS = ...
sampleStr.erase (sampleStr.begin (), sampleStr.end());
反转
string sampleStr ("Hello String! We will recerse you!);
reverse (sampleStr.begin (), sampleStr.end());
(2) STL 动态数组
vector
要实例化vector,需要指定要在该动态数组中存储的对象类型:
std ::vector<int> dynIntArray;
std::vector<float>dynFloatArray;
std::vector<Tuna>dynTunaArray;
使用push_back()在末尾插入元素。
vector<int> integers;
integers.push_back(8);
列表初始化:
vector<int> integers = {50,1,85,101};
或者
vector<int>integers {50,1,85,101}
使用insert()在指定位置插入元素
integers.insert(integers.end(),2,5); //在末尾插入两个5
删除vector中的元素
使用pop_back()删除末尾的元素。
理解大小和容量
vector的大小指的是实际存储的元素数,而vector的容量指的是在重新分配内存以存储更多元素前vector能够存储的元素数。因此,vector的大小 <= 容量。
我的理解: vector就像一个可以变化大小的水桶,一开始装10L的水,大小和容量都是10,现在把水倒了 装5L 那么大小就是5 容量还是10 ,再倒了 装20L的水,那么大小和容量都是20L。
查询大小
cout << "size: " << integers.size () << endl;
查询容量:
cout << "capacity" << integers.capacity() << endl;
deque
与vector非常相似,但支持在数组开头和末尾插入或删除元素。用push_front()和pop_front()
(3)STL list 和 forward_list
list是双向链表,优点主要是,插入和删除元素的速度快,且时间是固定的。
forward_list 是单向链表,只能沿着一个方向遍历。
实例化list
std::list<int> linkInts;
std::list<float> listFloats;
std:list<Tuna>listTuna;
要声明一个指向list中元素的迭代器,可以这样做:
std::list<int>::const_iterator elementInList;
和deque类似,要在list开头或者末尾插入元素,可使用,push_front(),push_back()
forward_list
插入元素只能用push_front(),而不能使用push_back()
(4) STL 集合类
容器set和multiset让程序员能够在容器中快速查找键,键是存储在一维容器中的值。set和multiset之间的区别在于,后者可以存储重复的值,而前者只能存储唯一的值。
为了实现快速搜索,STL set和multiset的内部结构像二叉树,这意味着将元素插入到set或multiset时将对其进行排序,以提高查找速度。
实例化std::set对象
类似于之前的
查找
auto elementFound = setInts.find(-1);
if (elementFOund != setInts.end())
{
cout......
}
(5) STL 映射类
map和multimap之间的区别在于,后者能够有存储重复的键,前者只能存储唯一的键
实例化map
#include <map>
using namespace std;
...
map <keyType, valueType, Predicate = std::less <keyType>> mapObj;
multimap <keyType, valueType, Predicate = std::less <keyType>> mapObj;
第三个参数是可选的,如果指定了键和值的类型,而省略了第三个模板的参数,将默认升序。
例如:
std :: map <int, string>mapIntTostr;
std :: multimap <int, string> mmapIntToStr;
十三、lambda表达式
lambda表达式是一种定义匿名函数对象的简洁方式,是c++11新增的。
定义lambda表达式
lambda表达式定义必须以方括号打头[ ]。这些括号告诉编译器,接下来是一个lambda表达式。方括号后面是一个参数列表,该参数列表与不使用lambda表达式时提供给operator()的参数列表相同。
[](type paraname) { }