C++ primer plus第15-16章笔记

第15章
  • 友元类可以声明在公有,私有,保护任意部分。
class Tv
{
public:
    friend class Remote; 
......
}
class Remote
{
.....
}

这样Remote可以使用Tv的私有成员。

class Tv;                       // forward declaration

class Remote
{
.....
}
class Tv
{
public:
    friend void Remote::set_chan(Tv & t, int c);
.....
}

这样只有Remote::set_chan(Tv & t, int c)成为了友元方法。

  • 注意互为友元的时候,对于使用Remote对象的Tv方法,其原型可在Remote类声明之前声明,但必须在Remote类声明之后定义。

  • 嵌套类

声明位置包含它的类是否可以使用它从包含它的类派生而来的类是否可以使用它在外部是否可以使用
私有部分
保护部分
公有部分是,通过类限定符来使用
  • 调用abort()函数可以终止程序(包含头文件cstdlib)

  • throw关键字表示引发异常,紧随其后的值指出了异常的特征。

  • C++通常通过将信息放在栈中来处理函数调用,普通函数程序会将函数指令的地址(返回地址)放到栈中,执行完毕后,程序再确定从哪开始执行。然而,函数异常终止之后,程序也将释放栈中的内存,但不会再释放栈的第一个返回地址后停止,而是继续释放栈,直至找到一个位于try块中的返回地址。然后控制权转到块尾的异常处理程序。

  • exception类

    • stdexcept异常类:分为logic_error和runtime_error类
      logic_error包括domain_error, invalid_argument, length_error, out_ot_bounds
      runtime_error包括range_error, overflow_error, underflow_error
    • bad_alloc异常:
      在头文件new中。在new请求内存出现分配问题时触发。
    • C++提供了一种在失败时返回空指针的new。用法:int * pi = new (std::nothrow) int;或者int *pa = new (std::nowthrow) int[500]
  • 异常同样可以继承。程序15.14,书634页的例子。

  • 未捕获异常不会导致程序立刻异常终止,程序会先调用terminate(),默认情况下,terminate()会调用abort()。可以调用set_terminate()函数来修改terminate()的行为。
    如果发生意外异常,会调用unexpected()函数,默认调用abort(),同样可以使用set_unexpected()函数来修改行为。

  • RTTI(运行阶段类型识别)

    • dynamic_cast运算符
      可以确定转换是否安全,例如:Superb* pm = dynamic_cast<Superb *>(pg)。如果能安全转换则返回对象的地址,否则返回一个空指针。
    • typeid运算符用于确定两个对象是否为同种类型。typeid(Megnificent) == typeid(*pg)如果pg是空指针,则会引发bad_typeid异常。
  • 类型转换符:

    • dynamic_cast在类层次结构中进行向上转换。
    • const_cast只能用于改变值为const或volatile
    • static_cast当转换的类型是原类型所属的类型时才可以使用。
    • reinterpret_cast用于底层编程,一般用不到。
第16章
  • string类的构造函数
    1.string(const char * s)
    说明:将string对象初始化为s指向NBTS。NBTS为null-byte-temnated string的缩写,表示以空字符结束的字符串——传统的C字符串。
    2.string(size_type n,char c)
    说明:创建一个包含n个元素的string对象,其中每个元素都被初始化为字符c
    3.string(const string & str,string size_type n = npos)
    说明:将string对象初始化为对象str中从位置pos开始到结尾的字符,或从位置pos开始的n个字符
    4.string()
    说明:创建一个的string对象,长度为0
    5.string(const char * s, size_type n)
    说明:将string对象初始化为s指向的NBTS中的前n字符,即使超过了NBTS端
    6.template< clas Iter > string(Iter begin,Iter end)
    说明:将string对象初始化为区间[begin,end]内的字符,其中begin和end的行为就像指针,用于指定位置,范围包括begin在内,但不包括end
    7.string(const string & str, string size_type pos = 0, size_type n = npos)
    将string对象初始化为对象str中从位置pos开始到结尾的字符,或从位置pos开始的n个字符。
    8.string(string && str) noexcept
    将一个string对象初始化为string对象的str,并可能修改str
    9.string(initializer_list< char > il)
    将一个string对象初始化为初始化列表il中的字符
    注意:区间是包前不包后。

  • string类的输入:

string stuff;
cin>> stuff;
getline(cin, stuff);
getline(stuff, ':');

char info[100];
cin>>info;
cin.getline(info,100);
cin.get(info, 100);
cin.getline(info,100,':');
  • string类的find方法:
    原型如下:
    (1)size_t find (const string& str, size_t pos = 0) const; //查找对象–string类对象
    (2)size_t find (const char* s, size_t pos = 0) const; //查找对象–字符串
    (3)size_t find (const char* s, size_t pos, size_t n) const; //查找对象–字符串的前n个字符
    (4)size_t find (char c, size_t pos = 0) const; //查找对象–字符
    结果:找到 – 返回 第一个字符的索引;没找到–返回 string::npos。

  • capacity()返回当前分配给字符串的内存块的大小,函数reserve()将字符串的容量设置为至少size. 如果size指定的数值要小于当前字符串中的字符数(亦即size < this→size()), 容量将被设置为可以恰好容纳字符的数值。最大的用处是为了避免反复重新分配缓冲区内存而导致效率降低,或者在使用某些STL操作(例如std::copy)之前保证缓冲区够大。

  • 智能指针:过期内存自动释放。

    • 内存指针必须显式转换,不能隐式转换,例如:
      shared_ptr<double> pd;
      double *p = new double;
      pd = p; //错误写法,隐式转换
      pd = shared_ptr<double>(p); // 显式转换

    • 注意不能让智能指针指向同一个对象,因为这样会删除一个对象两次。为了解决, auto_ptr和unique_ptr采用的是所有权概念,shared_ptr使用的是引用计数的方法。

    • 如果程序将unique_ptr赋给另外一个,在unique_ptr只作为一个临时右值时是允许的,但是如果要存在一段时间,不允许。
    • 使用new分配内存时,才能使用auto_ptr和shared_ptr,不能使用new []。unique_ptr有new和new[]的版本。
STL
  • 模板类vector代替数组,在< type >中声明数组中的类型,变量名后用括号()指明数组元素个数。有
函数作用
swap()交换
begin()返回第一个元素的迭代器
end()返回最后一个元素的迭代器
push_back()将元素添加到队尾,并自动加长长度
erase()有两个迭代器参数,删除指定区间的元素
insert()三个参数,第一个参数是插入的位置,后两个是插入区间
  • 迭代器:广义指针,可以是指针,也可以是对其执行类似指针的操作。声明:vector<double>::iterator pd可执行类似指针的操作。
pd = scores.begin();
*pd = 2;
++pd;
  • 超过结尾:一种迭代器,指向容器的最后一个元素后面的那个元素。

  • STL函数:

函数作用
for_each()函数指向容器每个元素,但是不能改变值
Random_shuffle()有两个迭代器参数,随机排列区间内的元素
sort()排序

- 迭代器类型:输入,输出,正向,双向,随机访问迭代器。

  • 固定时间和线性时间复杂度

  • 七种主要容器:

    • vector(前面已经介绍过)
    • deque表示双端队列,从开始位置插入和删除元素时间固定。
    • list表示双向链表,任意位置插入和删除时间固定,但是不能随机访问。其成员函数:
      assign() 给list赋值
      back() 返回最后一个元素
      begin() 返回指向第一个元素的迭代器
      clear() 删除所有元素
      empty() 如果list是空的则返回true
      end() 返回末尾的迭代器
      erase() 删除一个元素
      front() 返回第一个元素
      get_allocator() 返回list的配置器
      insert() 插入一个元素到list中
      max_size() 返回list能容纳的最大元素数量
      merge() 合并两个list
      pop_back() 删除最后一个元素
      pop_front() 删除第一个元素
      push_back() 在list的末尾添加一个元素
      push_front() 在list的头部添加一个元素
      rbegin() 返回指向第一个元素的逆向迭代器
      remove() 从list删除元素
      remove_if() 按指定条件删除元素
      rend() 指向list末尾的逆向迭代器
      resize() 改变list的大小
      reverse() 把list的元素倒转
      size() 返回list中的元素个数
      sort() 给list排序
      splice() 合并两个list
      swap() 交换两个list
      unique() 删除list中重复的元素
    • forward_list表示单链表,只需正向迭代器,不可反转。
    • queue是一种容器适配器,它给予程序员一种先进先出(FIFO)的数据结构。操作函数:
      back()返回最后一个元素
      empty()如果队列空则返回真
      front()返回第一个元素
      pop()删除第一个元素
      push()在末尾加入一个元素
      size()返回队列中元素的个数
    • priority_queue操作和queue相同,最大的元素被移到队首。
    • stack表示栈,操作:
      1.入栈:如s.push(x);
      2.出栈:如 s.pop().注意:出栈操作只是删除栈顶的元素,并不返回该元素。
      3.访问栈顶:如s.top();
      4.判断栈空:如s.empty().当栈空时返回true。
    • array
  • 关联容器:值和键关联在一起。

    • set:关联集合,可反转,排序,键值唯一,不能存储多个相同的值。例如:set<string> a
      模板第二个参数可选,可以是对键进行排序的比较函数或对象。默认有默认值。
      常用操作:
      1.元素插入:insert()
      2.中序遍历:类似vector遍历(用迭代器)
      3.反向遍历:利用反向迭代器reverse_iterator。
      例:
      set< int> s;
      ……
      set< int>::reverse_iterator rit;
      for(rit=s.rbegin();rit!=s.rend();rit++)
      4.元素删除:与插入一样,可以高效的删除,并自动调整使红黑树平衡。
      set< int> s;
      s.erase(2); //删除键值为2的元素
      s.clear();
      5.元素检索:find(),若找到,返回该键值迭代器的位置,否则,返回最后一个元素后面一个位置。
      set< int> s;
      set< int>::iterator it;
      it=s.find(5); //查找键值为5的元素
      if(it!=s.end()) //找到
      cout<<*it << endl;
      else //未找到
      cout<<”未找到”;
      6.自定义比较函数
      (1)元素不是结构体:
      例:
      //自定义比较函数myComp,重载“()”操作符
      struct myComp
      {
      bool operator()(const your_type &a,const your_type &b)
      [
      return a.data-b.data > 0;
      }
      }
      set< int,myComp>s;
      ……
      set< int,myComp>::iterator it;
      (2)如果元素是结构体,可以直接将比较函数写在结构体内。
      例:
      struct Info
      {
      string name;
      float score;
      //重载“<”操作符,自定义排序规则
      bool operator < (const Info &a) const
      {
      //按score从大到小排列
      return a.score < score;
      }
      }
      set< Info> s;
      ……
      set< Info>::iterator it;
    • multimap:可反转,经过排序的关联容器,但键和值的类型不同,且同一个键可能与多个值相关联。
      基本操作:
begin()返回指向第一个元素的迭代器
clear()删除所有元素
count()返回一个元素出现的次数
empty()如果multimap为空则返回真
end()返回一个指向multimap末尾的迭代器
equal_range()返回指向元素的key为指定值的迭代器对
erase()删除元素
find()查找元素
get_allocator()返回multimap的配置器
insert()插入元素
key_comp()返回比较key的函数
lower_bound()返回键值>=给定元素的第一个位置
max_size()返回可以容纳的最大元素个数
rbegin()返回一个指向mulitmap尾部的逆向迭代器
rend()返回一个指向multimap头部的逆向迭代器
size()返回multimap中元素的个数
swap()交换两个multimaps
upper_bound()返回键值>给定元素的第一个位置
value_comp()返回比较元素value的函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值