一、c到c++
c++包括:
头文件,异常处理,类和对象,STL,模板,Lambda表达式
头文件区别:
1、c语言头文件有29个,c++除了包含c的29个头文件以外,还另外多出来58个文件;
2、c带.h,c++在前面加一个c,例如:cstdio,cmath
异常处理:帮助debug
STL
起源于惠普实验室,STL的设计思想将算法和数据结构完全分离,分离后中间会有粘合剂——类型萃取来进行弥补。迭代器(iterator)是STL的重要组成部分,阅读源码的时候注意这个.
STL中提供了所有基本的数据结构,map有两种,一种底层是红黑树,另一种是哈希表实现的map
模板与Lambda表达式
要学习泛型编程,去看c++原模板编程,【参看代码】c语言存储任意类型的栈;想用c++训练函数式编程,去看Lambda表达式
- cin和cout是两个对象
- 命名空间std的作用:模块划分
总结:
c++包含c的所有特性,支持面向过程的编程范式,除此之外还支持面向对象,泛型编程,函数式编程,还有相关的异常处理机制,使得c++语言开发出来的相关程序的健壮性比较好;c语言也能实现面向对象、泛型编程等,但实现起来比较麻烦
二、数据类型:
Queue-类说明
queue类:队列
- 头文件: queue
- 命名空间:std
- 声明:queue<data_type> q;
其中<data_type>
是数据类型,如int, char, double等
q.front() | 查看队首元素 |
---|---|
q.empty() | 队列判空 |
q.push() | 入队 |
q.pop() | 出队 |
q.size() | 队列元素数量 |
Stack-类说明
Stack类:栈
- 头文件: stack
- 命名空间:std
- 声明:stack<data_type> q;
其中<data_type>
是数据类型,如int, char, double等
s.front() | 查看栈首元素 |
---|---|
s.empty() | 栈判空 |
s.push() | 入栈 |
s.pop() | 出栈 |
s.size() | 栈元素数量 |
String-类说明
string类:字符串
- 头文件: string
- 命名空间:std
- 声明:string s1, s2;
类似于c中的char
型
s1 == s2 | 字符串判等 |
---|---|
s1 < s2 | 字典序小于 |
s1 > s2 | 字典序大于 |
s1 += s2 | 字符串连接 |
s1.length() | 字符串长度 |
- s1.length()比strlen优秀,strlen每调用一次都会从头到尾扫一遍( O(n) ),而s1.length()是O(1)的查询操作
Hash_Map-类说明(非标准)
非标准:因为他不在std标准库中
红黑树是二叉树型结构,所以他的时间复杂度是O(logn),而加了个hash,代表O(1),底层是哈希
思考:为什么有更高级的hashmap我们不用,但却去使用红黑树的map
1、哈希扩容麻烦
2、红黑树天生是二叉排序树,中序遍历按序输出,哈希不可替代
hash_map类:字符串
- 头文件: <hash_map>
/ <ext/hash_map>
- 命名空间:__gnu_cxx;
- 声明:hash_map<key_type, value_type, hash_func> h;
- key_type:键值
- hash_func:是对键类型的哈希函数求解的
h.find(key) | 判断某个key值是否在hash_map中 |
---|---|
h[ key ] = value | 将value存储在key位上 |
h[ key ] | 访问key对应的value |
h.begin( ) | 哈希表的起始位置 |
h.end( ) | 哈希表的结束位置 |
Unordered_Map-类说明(C++11标准)
非排序map,底层hash实现
unordered_map类:字符串
- 头文件: unordered_map
- 命名空间:std
- 声明:unordered_map<key_type, value_type, hash_func> h;
- key_type:键值
- hash_func:是对键类型的哈希函数求解的
h.find(key) | 判断某个key值是否在unordered_map中 |
---|---|
h[ key ] = value | 将value存储在key位上 |
h[ key ] | 访问key对应的value |
h.begin( ) | 哈希表的起始位置 |
h.end( ) | 哈希表的结束位置 |
- 编译时加上编译选项
g++ -std=c++11
可编译成功
代码演示
-
头文件
<cstdio>
里有scanf
和printf
-
using namespace std
using namespace std//表示我要用标准命名空间中的所有符号
缺点:因为std中有很多标识符,工程中易产生命名冲突,所以尽量是用哪个就using哪个
实现存储任意类型数组
/* */
#include<iostream>
using std::cout;
using std::endl;
template<typename T>
struct arr {
public :
arr(int n) : n(n){
this->data = new T[n];
}
T &operator[](int ind) {
if (ind >= this->n) return this->temp;
return this->data[ind];
}
private :
T *data, temp;
int n;
};
int main() {
arr<int> a(10);
for (int i = 0; i < 10; i++ ) {
a[i] = i;
}
a[383838] = 200;
for (int i = 0; i < 10; i++ ) {
cout << a[i] << endl;
}
return 0;
}
/* 代码详解 */
#include<iostream>
using std::cout;
using std::endl;
template<typename T>//定义一个类型T
struct arr {
public :
/* 构造函数,参数n代表初始化大小
* n(n):初始化参数列表*/
arr(int n) : n(n){
/* data malloc */
/* this->data = (T *)malloc(sizeof(T) * n) */
this->data = new T[n];
}
/* 重载运算符:重载[],[]里传的应该是一个下标 */
/* 函数返回的是数字第ind位的引用 */
T &operator[](int ind) {
/*检查数组下表*/
/*当输入的下标大于所申请的数组长度时,说明该下表不合法,
返回当前对象里的temp;
*/
if (ind >= this->n) return this->temp;
return this->data[ind];//返回数组的第ind位
}
private :
T *data, temp;//存储任意类型数据
int n;
};
int main() {
arr<int> a(10);
for (int i = 0; i < 10; i++ ) {
a[i] = i;
}
//访问ind超限不会报,因为把[]重载了
a[383838] = 200;
for (int i = 0; i < 10; i++ ) {
cout << a[i] << endl;
}
return 0;
}