C++总结2

整理自[传智扫地僧教学视频][1]


  • 程序编译链接过程
    • gcc -E main.c -o main.i 宏定义展开 (文本) “-E 只运行与编译器”
    • gcc -S main.i -o main.s 生成汇编文件 (文本) “-S 产生汇编文件后停止编译”
    • gcc -c main.s -o main.o 生成目标文件 (二进制) “-c 取消链接”
    • gcc main.o -o app 生成可执行程序 (二进制)

泛型编程

函数模板

  • 函数模板的本质: 让类型参数化

    • 定义方法

      template <typename T>
      void myswap(T &a, T &b)
      {
          T temp;
          temp = a;
          a = b;
          b = temp;
      }
    • 调用方法

      myswap<int>(a, b); // 显示调用
      myswap(a, b);//自动类型推导
  • 函数模板和普通函数的区别及调用规则的研究
    • 函数模板要求严格的类型匹配, 不会进行自动类型转换。普通函数可以进行隐式的类型转换。
    • 函数模板可以像普通函数一样进行重载。
    • 在进行函数匹配时, c++编译器优先考虑普通函数。
    • 如果函数模板可以产生更好的匹配,则选择函数模板。
    • 可以通过空模版实参列表(<>)的语法限定编译器只通过模板匹配。
  • 函数模板机制
    • 编译器并不是把函数模板处理成能够处理任意类型的函数,而是通过具体类型产生不同的函数。进行了两次编译
      • 在声明的地方对模板代码进行编译
      • 在调用的地方对参数替换后的代码进行编译(与调用次数无关)

类模板

  • 单个类
    • 定义
    • 使用
    • 做函数参数 需指定具体类型
  • 继承中的模板类
    • 模板类派生普通类:需要具体化模板类(只能从具体的类派生)
    • 模板类派生模板类
  • 类模板函数(两次编译)
    • 所有模板函数写在类的内部(包括友元函数)
    • 所有模板函数写在类的外部
      • 在一个cpp文件中
      • 分开, .h 和 .cpp (hpp文件)。 main.cpp中要包含模板函数的实现文件。
      • 友元函数的实现要和声明写在一个文件里
        • 前置声明
        • 在类中友元声明时, 函数名后加<>
  • 模板类中的static
    • static成员属于某一具体类型的类。而不是由该类模板生成的不同的类。

类型转换

  • C 风格类型转换

    type a = (type)b

  • C++ 类型转换
    • static_cast: int a = static_cast<int> (b) 编译时进行类型检查
    • reinterpret_cast: 不同类型间强制类型转换,重新解释。 转换指针。
    • dynamic_cast: 子类和父类之间多态类型转换。向下转型,基类指针或引用安全转换为派生类的指针或引用。运行时类型识别RTTI,另一个操作符typeid
    • const_cast: 去掉const属性,即去除变量只读属性。形参为const,在函数中想修改非const实参。const实参仍不能修改(可能不报错,在函数内可以修改,但函数返回后又恢复原值)。
  • 要清楚要转的变量, 转换之前是何种类型,转换后是何种类型,转换的结果。一般情况下,不建议使用类型转换。

异常处理

  • 基本语法
    • throw; try catch
  • 异常是跨函数的
  • catch语句按照顺序进行检查
  • 接到异常后,可以不处理,继续throw
  • 异常是严格按照类型进行catch (不进行隐式类型转换)
  • 栈解旋: throw时,栈变量被自动销毁
  • 异常接口声明
    • void fun() throw(A, B, C) 只能抛出所列类型
    • void fun() 不写, 可以抛出任何类型
    • void fun() throw() 不抛出异常
  • 异常类型 & 异常变量的生命周期
    • 基础数据类型 int, char…
    • 类对象类型
      • 对象: throw时产生临时对象,再调用拷贝构造函数初始化catch子句中的形参(不是临时对象直接转化为形参)。
      • 对象的引用: 使用throw时产生的临时对象。不掉用拷贝构造函数。(对象和引用不能同时用于catch
      • 指针: 注意避免野指针 。 为避免野指针, throw时应使用new, 在异常处理中使用delete。
    • 综上,最好使用引用!将生命周期的管理交给编译器。
  • 异常的层次结构(继承在异常中的应用)

标准异常库

  • exception(基类)
    • bad_cast
    • runtime_error
      • overflow_error
      • underflow_error
      • range_error
    • logic_error
      • domain_error
      • invalid_argument
      • out_of_range
      • length_error
    • bad_alloc
  • virtual const char* what()

输入输出流

  • 标准IO流 cin cout cerr clog
    • cin类常用api
      • >> 遇见空格结束
      • cin.get()
      • cin.getline()
      • cin.ignore(N): 忽略缓冲区的N个字符。
      • cin.peek(): “偷窥”
      • cin.putback(): 将字符放回缓冲区
    • cout类常用api
      • cout.flush(): 刷新缓冲区
      • cout.put(): 输出字符
      • cout.write(): 输出字符串,可设置字符个数
        输出控制 成员函数方式(还有控制符方式)
      • cout.width(): 设置输出宽度
      • cout.fill(): 设置填充字符
      • cout.setf(): 设置标记
    • 格式化输出
  • 文件IO
    • 文件打开关闭
    • ASCII方式读写文件
    • 二进制方式读写文件

标准模板库STL

算法 容器 迭代器

  • 所有容器操作都是值语意,进行拷贝操作而非引用。所以STL容器内存储的元素必须能够被拷贝(必须提供拷贝构造函数,深拷贝)

string类 (封装了char指针)

  • 初始化 《C++ primer》 P76
  • 遍历
    • 数组方式 []
    • at(): 与[]的区别: at()可以抛出异常
    • 迭代器
  • 字符指针和string的转换
    • c_str()成员函数,返回指向string中字符串的指针
    • copy()成员函数,拷贝string中的字符串。值拷贝N个字符,不自动添加’\0’
  • 连接字符串
    • append()成员函数
    • operator+
    • operator+=
  • 查找和替换
    • find(): 返回要查找的子串首字符在原字符串中的下标(从零开始)。未找到返回-1. C中的strstr()
    • replace(): 从指定位置开始,删除N个字符,插入子串
  • 截断和插入
    • erase()
    • insert()
  • 大小写转换
    • transform()

容器

顺序容器: vector; deque; list;stack; 每个元素有固定的位置。取决于插入时机,与元素值无关

  • array 固定大小数组
  • vector
    • 动态数组,尾部添加或移除元素快,在中间和头部操作耗时。
    • 获取修改元素常用函数 返回引用,可当左值
      • at()
      • operator[]
      • front()
      • back()
    • 插入删除
      • insert()
      • push_back()
      • erase()
      • pop_back()
      • clear()
    • 遍历
      • 数组方式
      • 迭代器 迭代器失效问题
        • end()返回的迭代器指向的是最后一个元素之后的位置
        • rend()返回的是指向首元素之前的位置
    • vector对象是如何增长的
      在必须分配新空间时,会分配比实际需求更大的内存空间作为预留,而不是每次插入都进行分配。
  • deque
    • 双端数组,可以在尾部和头部快速插入和删除。
    • 额外支持的操作
      • push_front()
      • pop_front()
  • stack
    • top()
    • push()
    • pop()
    • size()
    • empty()
  • queue
    • push()
    • pop() 移除队首元素
    • back()
    • front()
    • size
    • empty
  • forward_list 单向链表
  • list
    • 双向链表容器,可以高效的插入和删除
    • 不支持随机存取,因此不支持at()和operator[]。 迭代器可以递增、递减,但不支持加数字
    • 插入删除
      • push_front()
      • pop_front()
      • push_back()
      • pop_back()
      • insert()
      • erase()
      • remove()成员函数
  • priority_queue 优先级队列 堆结构
    • 最大值(默认)优先级队列 privority_queue<int>privority_queue<int, vector<int>, less<int> >
    • 最小值优先队列 privority_queue<int, vector<int>, greater<int> >

关联容器: set; multiset; map; multimap; 元素位置取决于特定的排序准则,与插入顺序无关。

  • set 有序集合,所包含元素唯一。红黑树
    • 集合中的元素按一定顺序排列,元素插入过程是按排序规则插入,所以不能指定插入位置。默认情况从小到大。
      • set<int>set<int, less<int> >
      • set<int, greater<int> >
    • 插入操作和删除操作比vector快。
    • 不可以直接存取元素。 不支持at()和operator[]
    • 自定义数据类型排序
      • 仿函数/函数对象: 定义一个类(class、struct),类中重载函数调用操作符 set<int, Fun>
    • pair 对组
      • insert()函数返回值 pair
      • first
      • second
    • set的查找
      • count()
      • find()
      • equal_range()
      • lower_bound()
      • upper_bound()
  • multiset
    • 与set相比,同一个值可以出现多次
  • map 键值对(key, value)

    • 插入元素

      map<int, string> m;
      m.insert({1, "abc"});//方法一
      m.insert(pair<int, string> (1, "abc")); //方法二
      m.insert(make_pair(2, "def"));//方法三
      m.insert(map(int, string>::value_type(3, "ghi"));//方法四
      m[4] = "gkl";//方法五 
      //前四种重复插入会失败
      //第五种若map中有key = 4, 其内容被覆盖
    • 查找

      • find()
  • multimap

    • 与map相比,相同键可以出现多次。multimap不支持[]操作符。
    • 应用场景: 数据分组

STL算法

  • 函数对象: 重载了函数调用操作符的类,其对象成为函数对象。
    • 函数对象()的执行,很像函数调用, 因此又称仿函数
    • 函数对象与普通函数的区别
      • 函数对象是属于类对象,突破函数的概念,能保持调用状态信息。
      • 函数对象可当返回值。
    • 一元函数对象 函数参数1个
    • 二元函数对象 函数参数2个
    • 一元谓词
      • 函数参数1个
      • 函数返回值是bool型,可以作为一个判断式
      • 谓词可以是仿函数,也可以是回掉函数
    • 二元谓词
      • 函数参数两个
      • 返回类型是bool型
    • 预定义函数对象
    • 函数适配器
      • 绑定适配器
        • bind1st() 预定义函数对象和第一个参数绑定
        • bind2nd() 预定义函数对象和第二个参数绑定
      • 组合适配器
      • 指针函数适配器
      • 成员函数适配器
  • 理论总结
    • STL通过类模板技术,实现了数据类型和容器模型的分离
    • STL的迭代器技术实现了遍历容器的统一方法。
    • STL的算法,通过函数对象实现了自定义数据类型的算法运算。

常用算法

遇到问题追踪源码

  • 遍历算法

    • for_each()
      • 通过指定函数(函数对象或回掉函数)依次对一组迭代器范围内的元素进行访问, 可进行修改
      • 返回值是函数对象
      • 一般情况下,for_each()所使用的函数对象,参数是引用,没有返回值
    • transform()

      • 两种形式

        transform(b1, e1, b2, op) 若b2 = b1, 同for_each
        transform(b1, e1, b2, b3, op)

      • replace() 如果想以某值替换符合规则的元素,使用replace()更快

      • 一般情况下,transform()所使用的函数对象,参数一般不使用引用,而且函数有返回值。
  • 查找算法
    • adjacent_find() 查找一对相邻的重复元素, 找到则返回这对元素的第一个迭代器
    • binary_search() 在有序(二分法)序列中查找值,找到返回true.
    • count() 与给定值相等的元素个数 (基础数据类型)
    • count_if() 自定义数据类型
    • find() 基础数据类型
    • find_if() 自定义数据类型
    • equal_range()
  • 排序
    • merge(): 合并两个有序序列, 存放到另一个序列
    • sort()
    • random_shuffle(): 随机洗牌
    • reverse()
  • 拷贝和替换
    • copy()
    • replace() replace(v.begin(), v.end(), 3, 8) 将所有的3换位8
    • replace_if() 使用谓词,符合某一条件的变成新值
    • swap()
  • 算术
    • accumulate() 对指定范围内的元素求和,再加上一个指定的初始值
  • 生成
    • fill(): 将值赋值给指定范围内的所有元素
  • 集合算法 并不是只用于set类型
    • set_union() 并集
    • set_intersection() 交集
    • set_difference() 差集
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值