c到c++,类型说明,实现存储任意类型数组代码演示

一、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 可编译成功

代码演示

  1. 头文件<cstdio>里有scanfprintf

  2. 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;
}

猜你喜欢

转载自blog.csdn.net/tarawin/article/details/88536653